Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Python code run faster in a function?

def main():     for i in xrange(10**8):         pass main() 

This piece of code in Python runs in (Note: The timing is done with the time function in BASH in Linux.)

real    0m1.841s user    0m1.828s sys     0m0.012s 

However, if the for loop isn't placed within a function,

for i in xrange(10**8):     pass 

then it runs for a much longer time:

real    0m4.543s user    0m4.524s sys     0m0.012s 

Why is this?

like image 659
thedoctar Avatar asked Jun 28 '12 09:06

thedoctar


People also ask

Do functions make code run faster?

Functions CAN make code faster by coding logic once instead of repeating several times and thus reducing code size and resulting in better CPU cache usage. Functions CAN make code slower by copying parameters and hiding info from the optimization.

What makes Python so fast?

Due to being an interpreted and dynamically typed language, Python allows for extremely fast prototyping speeds but is unable to compete with the run times of C++, C, Fortran, as well as several other compiled languages.

Are functions slower in Python?

A function never makes those statements themselves slower. A Python function is just an object stored in a variable; you can assign functions to a different variable, replace them with something completely different, or delete them at any time.


1 Answers

Inside a function, the bytecode is:

  2           0 SETUP_LOOP              20 (to 23)               3 LOAD_GLOBAL              0 (xrange)               6 LOAD_CONST               3 (100000000)               9 CALL_FUNCTION            1              12 GET_ITER                     >>   13 FOR_ITER                 6 (to 22)              16 STORE_FAST               0 (i)    3          19 JUMP_ABSOLUTE           13         >>   22 POP_BLOCK                    >>   23 LOAD_CONST               0 (None)              26 RETURN_VALUE         

At the top level, the bytecode is:

  1           0 SETUP_LOOP              20 (to 23)               3 LOAD_NAME                0 (xrange)               6 LOAD_CONST               3 (100000000)               9 CALL_FUNCTION            1              12 GET_ITER                     >>   13 FOR_ITER                 6 (to 22)              16 STORE_NAME               1 (i)    2          19 JUMP_ABSOLUTE           13         >>   22 POP_BLOCK                    >>   23 LOAD_CONST               2 (None)              26 RETURN_VALUE         

The difference is that STORE_FAST is faster (!) than STORE_NAME. This is because in a function, i is a local but at toplevel it is a global.

To examine bytecode, use the dis module. I was able to disassemble the function directly, but to disassemble the toplevel code I had to use the compile builtin.

like image 50
ecatmur Avatar answered Sep 28 '22 00:09

ecatmur