1. Interesting Benchmarks (eu dll wrap, conventional dll wrap, machine procs)

Including the new regular expressions into the core made me do some thinking. I wonder how fast core is compared to just wrapping a DLL? I went through some additional work and I wrapped the compile and free commands of T-Rex in a few ways.

  1. Compiled the source (trex.c) into Euphoria and provided a trex.e library of wrapped machine_func/proc calls.
  2. Created a DLL that is basically the same as the be_trex.c, i.e. contains IS_ATOM_INT, MakeCString, MAKE_SEQ, etc... I then wrapped that with open_dll, c_func, c_proc calls.
  3. Conventional wrapping of an existing .dll file (i.e. open_dll, c_func, c_proc calls, wrapped is euphoria using things like allocate_string, peek_string).

Here are my results (1,000,000 iterations):

  1. 0.850 (0.0000004250 per) - built-in via machine funcs
  2. 0.970 (0.0000004850 per) - eu dll using direct c_func/proc calls
  3. 0.990 (0.0000004950 per) - eu dll (wrapped c_func/proc calls)
  4. 2.190 (0.0000010950 per) - conventional wrapped dll

Now, one thing I want to make mention of here. The above tests the compile and free methods, which are very simple methods. The actual find/exec method is quite complex. It involves C structures, many C string accesses, etc... If I were to wrap that w/the conventional wrapped dll, I believe the margin of difference would be much greater than it already is.

To further illustrate how I did these things, here is the trex_compile method:

Conventional wrapped dll

atom hTrexLibNew = define_c_func(hTrexLib, "trex_compile", { C_POINTER, 
C_POINTER }, C_POINTER) 
function trex_lib_new(sequence pattern) 
	atom hPattern = allocate_string(pattern), 
		hErrorMessage = allocate(4) 
 
	object result = c_func(hTrexLibNew, { hPattern, hErrorMessage }) 
 
	mem:free(hPattern) 
	mem:free(hErrorMessage) 
 
	return result 
end function 

eu dll

int _1trex_new(int pattern) 
{ 
    int _0, _1, _2; 
     
	// 	? 0 
	s1_ptr pattern_seq = SEQ_PTR(pattern); 
	char *re_str, *error = 0; 
 
	re_str = malloc(pattern_seq->length + 1); 
	MakeCString(re_str, pattern); 
 
	TRex *re = trex_compile(re_str, &error); 
 
	free(re_str); 
 
	DeRefDS(pattern); 
 
	if (re) { 
		if ((unsigned) re > (unsigned) MAXINT) 
			return NewDouble((double) (unsigned long) re); 
		return (unsigned long) re; 
	} else { 
		return NewString(error); 
	} 
} 
int meu_trex_new() __attribute__ ((alias ("_1trex_new"))); 

Corresponding euphoria wrapper:

atom hTrexNew = define_c_func(hTrex, "meu_trex_new", { E_SEQUENCE }, E_ATOM) 
function trex_new(sequence pattern) 
	return c_func(hTrexNew, { pattern }) 
end function 

machine func

object eu_trex_compile(object x) { 
	s1_ptr re_str_seq; 
	char *re_str, *error = NULL; 
	TRex *re; 
 
	re_str_seq = SEQ_PTR(SEQ_PTR(x)->base[1]); 
	re_str = EMalloc(re_str_seq->length + 1); 
	MakeCString(re_str, SEQ_PTR(x)->base[1]); 
 
	re = trex_compile(re_str, &error); 
 
	EFree(re_str); 
 
	if (re) { 
		if ((unsigned) re > (unsigned) MAXINT) 
			return NewDouble((double) (unsigned long) re); 
		return (unsigned long) re; 
	} else { 
		return NewString(error); 
	} 
} 

Corresponding euphoria wrapper:

public function new(sequence pattern) 
	return machine_func(M_TREX_COMPILE, { pattern, 0 }) 
end function 

The reason I did this was to really see what the difference was between conventional wrappings you can find on The Archive, for instance sqlite3 vs. creating a Euphoria specific DLL. The sqlite3.e has obvious advantages, platform independence. However, for complex wrappings, the additional work and deployment headaches might be justified given the above results.

Jeremy

new topic     » topic index » view message » categorize

2. Re: Interesting Benchmarks (eu dll wrap, conventional dll wrap, machine procs)

jeremy said...
  1. 0.850 (0.0000004250 per) - built-in via machine funcs
  2. 0.970 (0.0000004850 per) - eu dll using direct c_func/proc calls
  3. 0.990 (0.0000004950 per) - eu dll (wrapped c_func/proc calls)
  4. 2.190 (0.0000010950 per) - conventional wrapped dll

Now, one thing I want to make mention of here. The above tests the compile and free methods, which are very simple methods. The actual find/exec method is quite complex. It involves C structures, many C string accesses, etc... If I were to wrap that w/the conventional wrapped dll, I believe the margin of difference would be much greater than it already is.

Actually, I would suspect the oppositeunless you mean that you'd have to do a lot of the C-string and structure manipulation inside euphoria code. The overhead is in setting up the call to the dll. Once there, the speed should be about the same, so I'd expect the dll to catch up a bit. This would be consistent with Rob's traditional advice, that the more processing you do in the dll, the more benefit you get, because it can eventually overcome the overhead involved in setting up the external call.

This is one reason, BTW, that I had started (long ago, and maybe I'll get back to it some day sad) a statically linked euphoria/wxEuphoria project.

Matt

new topic     » goto parent     » topic index » view message » categorize

3. Re: Interesting Benchmarks (eu dll wrap, conventional dll wrap, machine procs)

mattlewis said...

Actually, I would suspect the oppositeunless you mean that you'd have to do a lot of the C-string and structure manipulation inside euphoria code. The overhead is in setting up the call to the dll. Once there, the speed should be about the same, so I'd expect the dll to catch up a bit. This would be consistent with Rob's traditional advice, that the more processing you do in the dll, the more benefit you get, because it can eventually overcome the overhead involved in setting up the external call.

This is one reason, BTW, that I had started (long ago, and maybe I'll get back to it some day sad) a statically linked euphoria/wxEuphoria project.

Just so I understand... What I am saying is that the find/exec method requires a lot of string access, pointer arithmitic, sequence creating, etc... Therefore, I believe that the eu dll (not the 100% eu code version) would be faster. I was thinking that doing all the string stuff in eu code (100% eu code version) would cause it to slow down more than it already is. Is that true?

Jeremy

new topic     » goto parent     » topic index » view message » categorize

4. Re: Interesting Benchmarks (eu dll wrap, conventional dll wrap, machine procs)

jeremy said...

Just so I understand... What I am saying is that the find/exec method requires a lot of string access, pointer arithmitic, sequence creating, etc... Therefore, I believe that the eu dll (not the 100% eu code version) would be faster. I was thinking that doing all the string stuff in eu code (100% eu code version) would cause it to slow down more than it already is. Is that true?

Looking back at the original post, I was clearly posting while decaffeinated. You were referring to the 'conventional dll' with lots of peek()ing and poke()ing being done in euphoria code, then using those to call out to the dll, and I apparently had trouble piecing together the prose with the code examples... getlost

Sorry for the confusion. This was also the conclusion I came to for wxEuphoria, and is why euphoria code passes euphoria objects, and I let the library do the conversion to wxStrings, etc.

Matt

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu