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 ...

Stefan
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to