Hello Elefterios,

On 12/11/2011 09:28 PM, Elefterios Stamatogiannakis wrote:
> I'm exploring pypy's code so as to speed up callbacks from C code, so as to
> speed up sqlite module's UDF.
> 
> I have some questions:
> 
>  - What are the differences between ctypes, rawffi and ffi. Where should each
> one of them be used?

_rawffi and _ffi are pypy-specific modules which expose the functionalities of
libffi.  _rawffi is old and slow, while _ffi is new and designed to be JIT
friendly.  However, at the moment of writing not all features of _rawffi have
been ported to _ffi yet, that's why we need to keep both around.

ctypes is implemented on top of _rawffi/_ffi.  The plan for the future is to
kill _rawffi at some point.

> - I see that ctypes is build on top of rawffi and ffi. If one wishes to work
> around ctypes (so as to not have ctype's overhead) which of the rawffi or ffi
> should he use? Which of the two is faster at runtime?

if possible, you should use _ffi. Note that so far with _ffi you can only call
functions, but e.g. you cannot define a callback.  If you are interested in
this stuff, you might want to look at the ffistruct branch, which adds support
for jit-friendly structures to _ffi.

Note that the public interface of _ffi is still fluid, it might change in the
future.  E.g., right now pointers are represented just by using python longs,
but we might want to use a proper well-typed wrapper in the future.

>  - How can i create a null pointer with _ffi?

As I said above, right now pointers are passed around as Python longs, so you
can just use 0 for the null pointer.

> And some remarks:
> 
> By only modifying pypy's sqlite module code, i managed to speed up sqlite's
> callbacks by 30% (for example there is a "for i in range(nargs)" line in 
> _sqlite3. _convert_params, which is a hot path).

that's nice. Patches are welcome :-)

> Also the following line in _ctypes/function.py ._wrap_callable
> 
> args = [argtype._CData_retval(argtype.from_address(arg)._buffer)
>                         for argtype, arg in zip(argtypes, args)]
> 
> Occupies a large percentage of the overall callback time (around 60-70%).

yes, I think that we never looked at performance of ctypes callback. Good spot
:-).

In other parts of ctypes there are hacks and shortcuts for performances. E.g.,
in _wrap_result we check whether the result type is primitive, and in that
case we just avoid to call _CData_retval.  Maybe it's possible to introduce a
similar shortcut there.

> Assuming that pypy JITs all of the above callback code. Is it a problem having
> all these memory allocations for each callback (my test does 10M callbacks)?
> Is there a way to avoid as much as possible all these memory allocations.
> 
> Right now CPython runs my test (10M callbacks) in 1.2 sec and pypy needs from
> 9 to 14 secs. I suspect that the large spread of pypy's run times are due to 
> GC.

I think it's "simply" because we never optimized callbacks. When I ported
ctypes from _rawffi to _ffi I got speedups up to 100 times faster. In case of
callbacks I expect a minor gain, because the JIT cannot inline across them,
but I still think there is room for lots of improvements.

If you are interested in trying it, I'll be more than glad to help you :)

ciao,
Anto
_______________________________________________
pypy-dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-dev

Reply via email to