[pypy-dev] cpyext performance
Stefan Behnel
stefan_ml at behnel.de
Tue Jul 3 11:33:16 CEST 2012
Hi,
I've been working with one of the modules in the Python benchmark suite,
namely nbody, and tried to make it run a little faster when compiled with
Cython in PyPy. I managed to get a massive speed-up by avoiding some
borrowed references during list iteration and using PySequence_GetItem()
instead, but now some 50-60% of the runtime are spent in Py_DecRef().
I tried debugging into it, but so far, all my attempts to get anything
useful out of PyPy or cpyext have failed.
I applied this obvious change
"""
diff -r 20258fbf10d0 pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py Sun Jul 01 10:02:26 2012 +0200
+++ b/pypy/module/cpyext/pyobject.py Tue Jul 03 11:18:22 2012 +0200
@@ -340,13 +340,13 @@
if obj.c_ob_refcnt == 0:
state = space.fromcache(RefcountState)
ptr = rffi.cast(ADDR, obj)
- if ptr not in state.py_objects_r2w:
+ try:
+ w_obj = state.py_objects_r2w.pop(ptr)
+ except KeyError:
# this is a half-allocated object, lets call the deallocator
# without modifying the r2w/w2r dicts
_Py_Dealloc(space, obj)
else:
- w_obj = state.py_objects_r2w[ptr]
- del state.py_objects_r2w[ptr]
w_type = space.type(w_obj)
if not w_type.is_cpytype():
_Py_Dealloc(space, obj)
"""
and it gave me a couple of percent, but beyond that, I'd have to know what
paths are actually taken here and where most of the time is spent.
Running it through callgrind yields nothing helpful, so I tried running it
in plain Python. That failed with an OverflowError in ll2ctypes.py:
"""
Traceback (most recent call last):
File "pypy-1.9/pypy/bin/py.py", line 187, in <module>
sys.exit(main_(sys.argv))
File "pypy-1.9/pypy/bin/py.py", line 86, in main_
space = option.make_objspace(config)
File "pypy-1.9/pypy/tool/option.py", line 45, in make_objspace
None, None, ['Space'])
File "pypy-1.9/pypy/objspace/std/__init__.py", line 1, in <module>
from pypy.objspace.std.objspace import StdObjSpace
File "pypy-1.9/pypy/objspace/std/objspace.py", line 18, in <module>
from pypy.objspace.std.complexobject import W_ComplexObject
File "pypy-1.9/pypy/objspace/std/complexobject.py", line 6, in <module>
from pypy.objspace.std.floatobject import W_FloatObject, _hash_float
File "pypy-1.9/pypy/objspace/std/floatobject.py", line 48, in <module>
class W_FloatObject(W_AbstractFloatObject):
File "pypy-1.9/pypy/objspace/std/floatobject.py", line 51, in W_FloatObject
from pypy.objspace.std.floattype import float_typedef as typedef
File "pypy-1.9/pypy/objspace/std/floattype.py", line 87, in <module>
_double_format, _float_format = detect_floatformat()
File "pypy-1.9/pypy/objspace/std/floattype.py", line 64, in
detect_floatformat
rffi.cast(rffi.DOUBLEP, buf)[0] = 9006104071832581.0
File "pypy-1.9/pypy/rpython/lltypesystem/lltype.py", line 1219, in
__setitem__
self._obj.setitem(i, val)
File "pypy-1.9/pypy/rpython/lltypesystem/ll2ctypes.py", line 620, in setitem
self._storage.contents._setitem(index, value, boundscheck=False)
File "pypy-1.9/pypy/rpython/lltypesystem/ll2ctypes.py", line 279, in _setitem
items = self._indexable(index)
File "pypy-1.9/pypy/rpython/lltypesystem/ll2ctypes.py", line 259, in
_indexable
PtrType = self._get_ptrtype()
File "pypy-1.9/pypy/rpython/lltypesystem/ll2ctypes.py", line 255, in
_get_ptrtype
raise e
OverflowError: array too large
"""
No idea what this is supposed to tell me, except that I apparently hit yet
another bug in PyPy.
Now, having wasted enough time with this, I'd be happy if someone else
could take over. I put the C code here that I used:
http://cython.org/nbodybench.tar.bz2
You can build it without Cython, just run the included setupdu.py script
over it and call
pypy -c 'import nbody; print(nbody.test_nbody(1))'
Then try to profile that.
Stefan
More information about the pypy-dev
mailing list