[Pyrex] Pyrex optimization chitchat

Paul Prescod paul.prescod at blastradius.com
Wed Jan 14 21:34:25 CET 2004


[sending from the office...sorry about using Outlook! Also sorry about
resending due to earlier bounce from office email address.]

> It would be really nice if one could declare builtins handling 
> with some sort of 'cdef type' extensions, rather than having 
> to build it into the Pyrex core.  

That's true. You would need to be very careful in the design of this
abstraction.

For instance, PySequence_SetItem, PyList_SetItem and PyList_SETITEM all
handle references a little bit different. So you probably have to have
syntax that says whether references are borrowed, stolen, lent or given by
the function.

And I don't know if Greg cares much about performance issues. It obviously
was not his highest priority (which is good!).

> For getting Pyrex into the Python core, it'd be a lot less 
> hassle to add a new e.g. 'sets.pxi' file than it would to hack the 
> Pyrex code generator again.  

Yes. But on the other hand, we need to keep two things in perspective.
First, this is just a performance hack. Sets (for example) work with Pyrex
out of the box just by virtue of its fallback to PyObject_GetItem. Second,
how often are new types added to the Python core with their own high
performance APIs? It isn't as if tomorrow someone is likey to add a
PyQueue_GetItem or PyBag_GetItem.

> E.g. something like
> 
> cdef pytype sequence int PySequence_Check(object):
>     __getitem__ = object PySequence_GetItem(object,int)
>     __contains__ = int PySequence_In(object,object) except -1
>     #... etc.

Interesting idea. Reminiscent of C++ type overlpading (in that it is done at
compile time rather than runtime the way it is in Python). It might also be
cool to define type conversions between arbitrary types in this way.

> Obviously, the syntax isn't even quarter-baked, but the idea is that it 
> would be nice to define these Python/C "protocols" for Pyrex to use, 
> including the function to call to do the type checking.  Thus, when one 
> assigns to a  'sequence' parameter or variable, the appropriate check is 
> performed.

I haven't even figured out the hacky way to get the Pyrex compiler to
generate these tests as type boundaries yet. ;)

> The other performance issues I've seen with Pyrex are attribute access, 
> and global names.  I don't know if these are fixed in 0.9, but in 
> previous versions, Pyrex uses PyObject_GetAttrString() for attribute 
> lookup, which requires memory allocation and various nested calls of 
> overhead before it then calls PyObject_GetAttr(). Calling the latter 
> directly should greatly improve attribute access speed, as it has 
> when I've manually done the work to make it happen in Pyrex.

So you would basically create the objects at module initialization time
instead of every time you 

The other obvious slow bit in PyRex is stuff like this:

    /* "/Users/pprescod/code/bisect/rxbisect0.pyx":13 */
    __pyx_2 = __Pyx_GetName(__pyx_b, "len"); if (!__pyx_2) {__pyx_filename =
__pyx_f[0]; __pyx_lineno = 13; goto __pyx_L1;}
    __pyx_3 = PyTuple_New(1); if (!__pyx_3) {__pyx_filename = __pyx_f[0];
__pyx_lineno = 13; goto __pyx_L1;}
    Py_INCREF(__pyx_v_a);
    PyTuple_SET_ITEM(__pyx_3, 0, __pyx_v_a);
    __pyx_4 = PyObject_CallObject(__pyx_2, __pyx_3); if (!__pyx_4)
{__pyx_filename = __pyx_f[0]; __pyx_lineno = 13; goto __pyx_L1;}
    Py_DECREF(__pyx_2); __pyx_2 = 0;
    Py_DECREF(__pyx_3); __pyx_3 = 0;
    Py_DECREF(__pyx_v_hi);
    __pyx_v_hi = __pyx_4;
    __pyx_4 = 0;
    goto __pyx_L2;
  }
  __pyx_L2:;

There are a few different ways to handle this depending on how important you
feel it is that len(foo) really always call __builtins__.len(foo) even if
the type of "foo" is known. If the dynamicity of "len" is untouchable then
you could define Pyrex modules like "listoptimizations" and
"dictoptimizations" with functions like "listlen" and "dictlen" that could
be statically bound rather than dynamically bound.

===

Also, maybe I'm just superstitious but is it possible that all of the
"gotos" would confuse the C compiler's optimizer? I'm not claiming I've done
any research into this.

 Paul Prescod




More information about the Pyrex mailing list