[Python-Dev] default of returning None hurts performance?
Steven D'Aprano
steve at pearwood.info
Tue Sep 1 15:04:50 CEST 2009
On Tue, 1 Sep 2009 05:51:49 pm Scott Dial wrote:
> Raymond Hettinger wrote:
> >> I was just wondering if a bytecode for a superinstruction of the
> >> common sequence:
> >>
> >> 6 POP_TOP
> >> 7 LOAD_CONST 0 (None)
> >> 10 RETURN_VALUE
> >>
> >> might be worth it.
> >
> > [Collin Winter]
> >
> >> I doubt it. You'd save a bit of stack manipulation, but since this
> >> will only appear at the end of a function, I'd be skeptical that
> >> this would make any macrobenchmarks (statistically) significantly
> >> faster.
> >
> > I concur with Collin. And since it appears only at the end of a
> > function, the optimization doesn't help inner-loops in a function
> > (where most of the time usually spent).
>
> I fail to understand this crude logic. How often is the inner-loop
> really going to solely call C code? Any call to Python in an
> inner-loop is going to suffer this penalty on the order of the number
> of loop iterations)?
Most functions don't suffer this penalty. Consider the following two
functions:
def g(x):
return x()
def h(x):
x()
Now disassemble:
>>> dis.dis(g)
2 0 LOAD_FAST 0 (x)
3 CALL_FUNCTION 0
6 RETURN_VALUE
>>> dis.dis(h)
2 0 LOAD_FAST 0 (x)
3 CALL_FUNCTION 0
6 POP_TOP
7 LOAD_CONST 0 (None)
10 RETURN_VALUE
The first doesn't suffer any such default "return None" penalty, and so
won't gain any performance benefit from optimizing it. It is only the
subset of functions which don't explicitly return anything which will
see any potential benefit. Let me call such functions "procedures" to
avoid confusion with those functions which won't see any benefit.
While procedures may see some benefit, it's a trivial amount, probably
not worth the extra complexity. According to Gregory's tests, the
difference is approximately 2% on a trivial do-nothing function.
According to my tests on my PC, I might hope to save somewhat less than
0.1 microsecond per procedure call as an absolute saving. As a relative
saving though, it will most likely be insignificant: for comparison's
sake, urllib2.Request('http://example.com') takes around 150μs on my
machine, and math.sin(1.1) around 90μs. For any procedure which does
non-trivial amounts of work, saving 0.1μs is insignificant, no matter
how many times it is called inside a loop.
--
Steven D'Aprano
More information about the Python-Dev
mailing list