On 23 March 2010 09:09, Andreas Raab andreas.raab@gmx.de wrote:
On 3/22/2010 9:21 PM, Andreas Raab wrote:
Also, I was under the impression that Alien FFI was faster than the standard FFI.
Oh, dear. This is hearsay, right? I.e., neither you nor anyone who claims it have ever ever run an actual benchmark, have you?
I thought it'd be fun to make a little benchmark so here we go. I'm using the most trivial example, namely the call to glGetError() which should be done early and often :-) Using the FFI (from CroquetGL) this looks like here:
ogl := OpenGL newIn: (0@0 corner: 10@10). time := [1 to: 1000000 do:[:i| ogl glGetError]] timeToRun. ogl destroy.
This takes about 435 msecs. Now the same with AlienOpenGL in Pharo:
drawable := OpenGLSurface newIn: (0@0 corner: 10@10). ogl := AlienOpenGLLibrary uniqueInstance. time := [1 to: 1000000 do:[:i| ogl glGetError]] timeToRun. drawable close.
This takes 8372 msecs. Whoopsie. That's a factor of 20x AlienOpenGL is slower for the same C call. But okay, that may not be a fair comparison due to the naive use of Alien. Let's be more clever, look up the method just once and invoke it:
drawable := OpenGLSurface newIn: (0@0 corner: 10@10). ogl := AlienOpenGLLibrary uniqueInstance. alienMethod := ogl alienMethodNamed: 'glGetError'. time := [1 to: 1000000 do:[:i| error := GLEnum new. alienMethod primFFICallResult: error. ]] timeToRun. drawable close.
i don't know how to load this code, could you put error := GLEnum new. out of block and run it again?
This still takes 3589 msecs. Whoops, it did it again. Even with the more elaborate use Alien is still 8x slower than the FFI. That's the cost of doing marshalling in Squeak and the effect it has on Alien performance when compared with the FFI.
It is expected to see that marshalling/converting types takes most of the time, while rest should be same, because it straightforward: push arguments, make a call and return result. So, at some cases (not at all), one could prepare arguments and return value holder and then use it in calls, avoiding allocating & converting them each time. For instance, when you passing a string (char*), one may use a CString object (a null-terminated String), and pass it into Alien without conversion, while FFI allocates a null-terminated strings on heap, copying String contents to that buffer and then using them as arguments to a function. So its hard to say, which way is better.
Cheers, - Andreas