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?
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With