Global VS Local Space in Python

I’ve been trying to understand how different is accessing a global name space vs a local name space, ideally we don’t care defining attributes over global space. But there is a huge difference in the way they both gets accessed.

Note: I’m doing this with Python3.6, on machine with Intel Core i7 with 9MB cache with 6cores and 16GB Memory.

Let’s say I’ve a simple program to loop for 50 million times, run this in different name spaces.

Global space.

If we put statements at modele level, they’d run purely on global space, all the storage gets pushed in globals.

for i in range(50000000):
    pass

If we run the above program, it took 1.48147 seconds.

Local space.

If we move the looping logic inside a function, compiler would genertae local namespace leevl instructions.

def foo():
    for i in range(50000000):
        pass

If we run the above program, it took 0.8058 seconds.

Why is the difference?

Lets see a bit inside, how these two gets compiled and interpreted with bytecode.

Global bytecode.

  1           0 SETUP_LOOP              20
              2 LOAD_NAME                0 (range)
              4 LOAD_CONST               0 (50000000)
              6 CALL_FUNCTION            1
              8 GET_ITER
        >>   10 FOR_ITER                 8 (to 20)
             12 STORE_NAME               1 (i)

  2          14 LOAD_NAME                1 (i)
             16 POP_TOP
             18 JUMP_ABSOLUTE           10
        >>   20 POP_BLOCK
             22 LOAD_CONST               1 (None)
             24 RETURN_VALUE

Local bytecode.

  3           0 SETUP_LOOP              20
              2 LOAD_GLOBAL              0 (range)
              4 LOAD_CONST               1 (50000000)
              6 CALL_FUNCTION            1
              8 GET_ITER
        >>   10 FOR_ITER                 8 (to 20)
             12 STORE_FAST               0 (i)

  4          14 LOAD_FAST                0 (i)
             16 POP_TOP
             18 JUMP_ABSOLUTE           10
        >>   20 POP_BLOCK
             22 LOAD_CONST               0 (None)
             24 RETURN_VALUE

If we compare both the codes, there is a slight difference in the way the variable i gets stored and loaded, in global name space it’s being done with STORE_NAME and LOAD_NAME, same in local space is handled with STORE_FAST and LOAD_FAST.

This is where the difference is, STORE_NAME stores the variable in a dict with variable as key and value as value, STORE_FAST stores the value in a local array with a predefined compiled time index.

So, Storing a value to dict includes many things, it has to add value and readjust the hash table for indexing, this makes transactions slow.

But, storing and retriving in an array with compiled time index is really fast, that’s why the there is a huge difference in execution times.

Published: May 10 2017

  • category:
blog comments powered by Disqus