The other day I was doing some Python benchmarking and I came across something interesting. Below are two loops that do more or less the same thing. Loop 1 takes about twice as long as loop 2 to execute.
Loop 1:
int i = 0 while i < 100000000: i += 1
Loop 2:
for n in range(0,100000000): pass
Why is the first loop so much slower? I know it's a trivial example but it's piqued my interest. Is there something special about the range() function that makes it more efficient than incrementing a variable the same way?
While loop cannot be iterated on Generators directly. For loop with range() uses 3 operations. range() function is implemented in C, so, its faster. On basis of disassembly, for loop is faster than while loop.
In this case, the for loop is faster, but also more elegant compared to while. Please, have in mind that you can't apply list comprehensions in all cases when you need loops. Some more complex situations require the ordinary for or even while loops.
Using for: % Time elapsed: 0.0010001659 seconds. Using while: % Time elapsed: 0.026000023 seconds. The main reason that While is much slower is because the while loop checks the condition after each iteration, so if you are going to write this code, just use a for loop instead.
Yes, there is a huge difference between while and for. The for statement iterates through a collection or iterable object or generator function. The while statement simply loops until a condition is False. It isn't preference.
see the disassembly of python byte code, you may get a more concrete idea
use while loop:
1 0 LOAD_CONST 0 (0) 3 STORE_NAME 0 (i) 2 6 SETUP_LOOP 28 (to 37) >> 9 LOAD_NAME 0 (i) # <- 12 LOAD_CONST 1 (100000000) # <- 15 COMPARE_OP 0 (<) # <- 18 JUMP_IF_FALSE 14 (to 35) # <- 21 POP_TOP # <- 3 22 LOAD_NAME 0 (i) # <- 25 LOAD_CONST 2 (1) # <- 28 INPLACE_ADD # <- 29 STORE_NAME 0 (i) # <- 32 JUMP_ABSOLUTE 9 # <- >> 35 POP_TOP 36 POP_BLOCK
The loop body has 10 op
use range:
1 0 SETUP_LOOP 23 (to 26) 3 LOAD_NAME 0 (range) 6 LOAD_CONST 0 (0) 9 LOAD_CONST 1 (100000000) 12 CALL_FUNCTION 2 15 GET_ITER >> 16 FOR_ITER 6 (to 25) # <- 19 STORE_NAME 1 (n) # <- 2 22 JUMP_ABSOLUTE 16 # <- >> 25 POP_BLOCK >> 26 LOAD_CONST 2 (None) 29 RETURN_VALUE
The loop body has 3 op
The time to run C code is much shorter than intepretor and can be ignored.
range()
is implemented in C, whereas i += 1
is interpreted.
Using xrange()
could make it even faster for large numbers. Starting with Python 3.0 range()
is the same as previously xrange()
.
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