[Python-Dev] default of returning None hurts performance? (original) (raw)

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 POPTOP >> 7 LOADCONST 0 (None) >> 10 RETURNVALUE >> >> 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