Stefan Behnel wrote: > Nick Joyce, 22.02.2010 21:11: > >> The current PyAMF code is littered with PyDict_* calls so I am in the >> process of refactoring it to make use of this syntactic sugar. >> >> When I generate the C code (using Cython 0.12.1) for the above function, >> the resulting C code will use PyDict_SetItem for the assignment >> statement but will use PyObject_GetItem on line 6. I have attached a >> snippet of the generated C [pyobject_getitem.c]. >> > > To me, the reason why this wasn't done before is that the Python semantics > often are not what one really wants here. The corresponding code that uses > PyDict_GetItem() is faster when the key is found, but it is very > inefficient when the key is not found. The function would simply return > NULL in this case, which is easy and fast to test for in C code. Usually, > when I needed pure speed here, I needed it for the failure case, so I used > a direct C-API call anyway. > > Robert is right in suggesting that it might not even be worth it. Even a > virtual call to the tp_getitem slot (which is a pretty direct result of the > PyObject_GetItem() call) is likely not that much slower than a call to > PyDict_GetItem(), given the overhead of emulating the Python semantics > around the call. Only benchmarking can tell if this brings more than a > negligible 4% speedup 'on average'. > > It would certainly bring much more if Cython could deduce what the result > is used for afterwards, and then reduce the true Python semantics to what > is really needed. E.g. this code: > > cdef dict d = ... > try: > item = d['test'] > except KeyError: > item = d['test'] = some_value > > could be reduced to this pseudo code: > > try: > if d is None: > raise TypeError(...) > item = PyDict_GetItem(d, 'test') > if item is NULL: > goto except_handler > Py_INCREF(item) > except KeyError: > except_handler: > PyDict_SetItem(d, some_value) > Py_INCREF(some_value) > item = some_value > > But that's certainly not trivial with the current compiler infrastructure. > It would be possible to see that a KeyError is caught around a dict access, > so that it would no longer be necessary to actually raise the KeyError in > the first place. > > Then again, this could happen: > > try: ... > except KeyError: > print sys.exc_info() > > Well, well, Python ... > > How about just optimizing "d.get(key[, default])" if it isn't already for this case, and document that [] is slower?
Dag Sverre _______________________________________________ Cython-dev mailing list [email protected] http://codespeak.net/mailman/listinfo/cython-dev
