Is unpacking faster than indexing?
3 min read
This is a strange story.
One morning, I woke up and wrote a few lines of code. Then, there came an interesting situation. I need to assign two elements of an array to two variables. There are many ways of achieving this in python.
const [x,y] = items;
Suppose, I've got an array
[1,2] and I need to assign two variables to this value. Something like follow:
a = 1 b = 2
I did the natural thing I was used to doing, unpacking the variable.
a, b = items
This works with charm. But suddenly I remember of an another way. What if I index the array and grab the elements that way.
a, b = items, items
a = items b = items
Now, I want to profile this code. I know this is over-engineering at max but let's see what exactly happens.
First I wrote the same implementation in python and disassembled the code.
In : def x(): ...: a , b = items ...: return ...: In : def y(): ...: a = items ...: b = items ...: return ...: In : dis(x) 2 0 LOAD_GLOBAL 0 (items) 2 UNPACK_SEQUENCE 2 4 STORE_FAST 0 (a) 6 STORE_FAST 1 (b) 3 8 LOAD_CONST 0 (None) 10 RETURN_VALUE In : dis(y) 2 0 LOAD_GLOBAL 0 (items) 2 LOAD_CONST 1 (0) 4 BINARY_SUBSCR 6 STORE_FAST 0 (a) 3 8 LOAD_GLOBAL 0 (items) 10 LOAD_CONST 2 (1) 12 BINARY_SUBSCR 14 STORE_FAST 1 (b) 4 16 LOAD_CONST 0 (None) 18 RETURN_VALUE In :
Do you see the extra overhead when I index the value? First, it need to load the constant i.e. index value, then perform the subscription. The store the value in
a. This is a long way of doing it.
If I look at the other code, which is unpacking. One instruction
UNPACK_SEQUENCE is capable of returning all the values and it's followed by two store instructions.
Even by intuition, I suppose the first function
(x) will run faster.
Now, let's compare the execution time.
In : %timeit x() 84.3 ns ± 3.59 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each) In : %timeit y() 108 ns ± 2.42 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
To no surprise, the unpacking beats the indexing by around ~24ns. This isn't the kind of optimization you should be thinking when writing a code. Write a clean, readable testable code.
Don't abuse your codebase with lines like the following:
a ,= items # use this b = items