[Pyrex] slow constructor call
Joachim Saul
saul at gfz-potsdam.de
Mon Dec 15 16:59:49 CET 2003
Hi there,
I am currently migrating a set of Python extension types for
seismological analysis to Pyrex, which I had written by hand using
the Python/C API. I really like the clean Pyrex code resulting
from the migration, which is much easier to maintain.
One of the classes (actually the first which I have migrated, in
order to compare performance) is a "Time" class to allow simple
time arithmetics. Unfortunately, calling the constructor of the
Pyrex version (which calls the same C functions as the
corresponding C version) is slower by about a factor of 4.
Interestingly, operations which don't require calling the
constructor, such as in-place subtractions, are practically
exactly as fast in the Pyrex as in the C version.
Comparing the codes brought out that the principal difference
appears to be that in Pyrex-generated code "PyObject_CallObject"
is called to create a new instance, whereas in my older codes use
"PyObject_NEW", which appears to be faster. I am not so familiar
with the internals, but PyObject_CallObject appears to produce the
overhead.
Is there a faster way to construct a class instance? In this
particular case the difference is really not a big deal in
practice, but *if* there is currently a faster way, I'd certainly
like to take advantage of it.
Cheers,
Joachim
BTW: The definition of my "Time" class is as follows (trimmed to the
most essential for clarity; all that has a "SeisTime" prefix is C):
cdef class Time:
cdef SeisTime *t
def __init__(self, obj=None):
if obj:
self.t = SeisTime_newFromString(obj)
else:
self.t = SeisTime_new(0, 0.)
def __dealloc__(self):
SeisTime_del(self.t)
def __copy__(self):
cdef Time new
new = Time() # SLOW
# copy data parts only:
SeisTime_copy(new.t, self.t)
return new
def __sub__(Time left, right): # slow
cdef Time tmp
cdef double dt
tmp = Time() # this is what makes it so slow
if isnumber(right): # isnumber is a C function
SeisTime_copy(tmp.t, left.t)
dt = right # needed for conversion
SeisTime_add_float(tmp.t, -dt)
return tmp
return NotImplemented
def __isub__(self, double other): # very fast
SeisTime_add_float(self.t, -other)
return self
More information about the Pyrex
mailing list