[Python-Dev] Speed up function calls

Neal Norwitz nnorwitz at gmail.com
Tue Jan 25 00:37:04 CET 2005


On Mon, 24 Jan 2005 03:11:05 -0500, Raymond Hettinger <python at rcn.com> wrote:
>
> Replacing METH_O and METH_NOARGS seems straight-forward, but
> METH_VARARGS has much broader capabilities.  How would you handle the
> simple case of "O|OO"?  How could you determine useful default values
> (NULL, 0, -1, -909, etc.)?

I have a new version of the patch that handles this condition.
I pass NULLs for non-existant optional parameters.  In your
case above, the arguments passed would be:

    (obj, NULL, NULL)

This is handled pretty cleanly in the callees, since it is
pretty common to initialize optional params to NULL.

> If you solve the default value problem, then please also try to come up
> with a better flag name than METH_ARGS which I find to be indistinct
> from METH_VARARGS and also not very descriptive of its functionality.
> Perhaps something like METH_UNPACKED would be an improvement.

I agree METH_ARGS is a poor name.  UNPACKED is fine with me.
If I don't hear a better suggestion, I'll go with that.

> > The drawbacks are:
> >  * the defn of the MethodDef (# args) is separate from the function
> defn
> >  * potentially more error prone to write C methods???
> 
> No worse than with METH_O or METH_NOARGS.

I agree, plus the signature changes if METH_KEYWORDS is used.
I was interested if others viewed the change as better, worse,
or about the same.  I agree with /F that it could be a disaster
if it really is more error prone.  I don't view the change as
much different.  Do others view this as a real problem? 

> If speed is the main advantage being sought, it would be worthwhile to
> conduct more extensive timing tests with a variety of code and not using
> a debug build.  Running test.test_decimal would be a useful overall
> benchmark.

I was hoping others might try it out and see.  I don't have access
to Windows, Mac, or other arches.  I only have x86 and amd64.
It would also be interesting to test this on some real world code.

I have tried various builtin functions and methods and the gain
seems to be consistent across all of them.  I tried things like
dict.get, pow, isinstance.  Since the overhead is fairly constant,
I would expect functions with more arguments to have an even
better improvement.

> In theory, I don't see how you could improve on METH_O and METH_NOARGS.
> The only saving is the time for the flag test (a predictable branch).
> Offsetting that savings is the additional time for checking min/max args
> and for constructing a C call with the appropriate number of args.  I
> suspect there is no savings here and that the timings will get worse.

I think tested a method I changed from METH_O to METH_ARGS and could
not measure a difference.  A beneift would be to consolidate METH_O,
METH_NOARGS, and METH_VARARGS into a single case.  This should
make code simpler all around (IMO).

> In all likelihood, the only real opportunity for savings is replacing
> METH_VARARGS in cases that have already been sped-up using
> PyTuple_Unpack().  Those can be further improved by eliminating the time
> to build and unpack the temporary argument tuple.

Which this patch accomplishes.

> Even then, I don't see how to overcome the need to set useful default
> values for optional object arguments.

Take a look at the updated patch (#2).  I still think it's pretty clean and an
overall win.  But I'd really like to know what others think.  I also implemented
most (all?) of METH_O and METH_NOARGS plus many METH_VARARGS, so
benchmarkers can compare a difference with and without the patch.

Neal


More information about the Python-Dev mailing list