Bizarre additional calling overhead.

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sat Nov 3 01:12:16 CET 2007


On Fri, 02 Nov 2007 17:08:06 -0500, Chris Mellon wrote:

>>>> def test_func():
> ...     pass
> ...
>>>> import new
>>>> test_func2 = new.function(test_func.func_code, {}, "test_func2")

[snip results of timeit]

> Why almost twice the calling overhead for a dynamic function?

When I time the functions, I get a lot of variability. The minimum value 
is probably the best one to look at:

>>> min(timeit.Timer("test_func()", 
... "from __main__ import test_func").repeat(20))
0.35664010047912598
>>> min(timeit.Timer("test_func2()", 
... "from __main__ import test_func2").repeat(20))
0.68138217926025391


Disassembling the code does not give any hints:

>>> import dis
>>> dis.dis(test_func)
  2           0 LOAD_CONST               0 (None)
              3 RETURN_VALUE
>>> dis.dis(test_func2)
  2           0 LOAD_CONST               0 (None)
              3 RETURN_VALUE

Which is what we should expect, because both functions have the same code:

>>> test_func.func_code is test_func2.func_code
True


But try this:

>>> test_func3 = new.function(test_func.func_code, 
... globals(), 'test_func3')
>>> min(timeit.Timer("test_func3()", 
... "from __main__ import test_func3").repeat(20))
0.35772204399108887


Hmmm... it looks like the difference in speed has to do with the globals, 
not the fact that it is created dynamically. I wonder why?




-- 
Steven.



More information about the Python-list mailing list