Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why python list slice assignment eats memory?

I'm fighting a memory leak in a Python project and spent much time on it already. I have deduced the problem to a small example. Now seems like I know the solution, but I can't understand why.

import random

def main():
    d = {}
    used_keys = []
    n = 0
    while True:
        # choose a key unique enough among used previously
        key = random.randint(0, 2 ** 60)
        d[key] = 1234 # the value doesn't matter
        used_keys.append(key)
        n += 1
        if n % 1000 == 0:
            # clean up every 1000 iterations
            print 'thousand'
            for key in used_keys:
                del d[key]
                used_keys[:] = []
                #used_keys = []

if __name__ == '__main__':
    main()

The idea is that I store some values in the dict d and memorize used keys in a list to be able to clean the dict from time to time.

This variation of the program confidently eats memory never returning it back. If I use alternative method to „clear” used_keys that is commented in the example, all is fine: memory consumption stays at constant level.

Why?

Tested on CPython and many linuxes.

like image 719
nkrkv Avatar asked Jul 30 '10 08:07

nkrkv


People also ask

When slicing in Python What does the 2 in [:: 2 specify?

Second note, when no start is defined as in A[:2] , it defaults to 0. There are two ends to the list: the beginning where index=0 (the first element) and the end where index=highest value (the last element).

Does Python slicing make a copy?

The short answer. Slicing lists does not generate copies of the objects in the list; it just copies the references to them. That is the answer to the question as asked.

Is Python slicing inclusive?

One way to remember this is that the start point is inclusive and the end point is exclusive. In other words the slice will be from the start point up to but not including the end point. For the more visual folks another way is to to picture a wall before each value in the sequence.

What is slice assignment in Python?

Slice assignment is a little-used, beautiful Python feature to replace a slice with another sequence. Simply select the slice you want to replace on the left and the values to replace it on the right side of the equation.


1 Answers

Here's the reason - the current method does not delete the keys from the dict (only one, actually). This is because you clear the used_keys list during the loop, and the loop exits prematurely.

The 2nd (commented) method, however, does work as you assign a new value to used_keys so the loop finishes successfully.

See the difference between:

>>> a=[1,2,3]
>>> for x in a:
...    print x
...    a=[]
...
1
2
3

and

>>> a=[1,2,3]
>>> for x in a:
...    print x
...    a[:] = []
...
1
>>>
like image 130
adamk Avatar answered Oct 16 '22 16:10

adamk