Understanding python memory allocation and freeing up

I recently met this article on python memory allocation.

This page describes python memory usage, and there is an example showing the depth of a list of integers. I did the test myself in Python 2.7

Line # Mem usage Increment Line Contents ================================================ 4 28.051 MiB 0.000 MiB @profile 5 def function(): 6 59.098 MiB 31.047 MiB x = list(range(1000000)) # allocate a big list 7 107.273 MiB 48.176 MiB y = copy.deepcopy(x) 8 99.641 MiB -7.633 MiB del x 9 99.641 MiB 0.000 MiB return y 

therefore delete x directly removes only x and all references to integer to x right?

Doing this also did not help (so what is the difference between del x and del x [:]?):

 Line # Mem usage Increment Line Contents ================================================ 4 28.047 MiB 0.000 MiB @profile 5 def function(): 6 59.094 MiB 31.047 MiB x = list(range(1000000)) # allocate a big list 7 107.270 MiB 48.176 MiB y = copy.deepcopy(x) 8 99.637 MiB -7.633 MiB del x[:] 9 99.637 MiB 0.000 MiB return y 

And unlike deepcopy, if I use a copy, after deleting it seems that the memory is restored to its previous state, when x is newly created

 Line # Mem usage Increment Line Contents ================================================ 4 28.039 MiB 0.000 MiB @profile 5 def function(): 6 59.090 MiB 31.051 MiB x = list(range(1000000)) # allocate a big list 7 66.895 MiB 7.805 MiB y = copy.copy(x) 8 59.262 MiB -7.633 MiB del x[:] 9 59.262 MiB 0.000 MiB return y 

For dict:

 Line # Mem usage Increment Line Contents ================================================ 4 28.051 MiB 0.000 MiB @profile 5 def function(): 6 100.523 MiB 72.473 MiB x = dict((e, e) for e in xrange(1000000)) 7 183.398 MiB 82.875 MiB y = copy.deepcopy(x) 8 135.395 MiB -48.004 MiB del x 9 135.395 MiB 0.000 MiB return y 

And for the list of lists (compare with an integer, I suppose that del x or del x [:] only removes this huge list of arrays on the heap?):

 Line # Mem usage Increment Line Contents ================================================ 4 28.043 MiB 0.000 MiB @profile 5 def function(): 6 107.691 MiB 79.648 MiB x = [[] for _ in xrange(1000000)] 7 222.312 MiB 114.621 MiB y = copy.deepcopy(x) 8 214.680 MiB -7.633 MiB del x[:] 9 214.680 MiB 0.000 MiB return y 

Therefore, I want to ask:

  • So, if there is no way to get back the memory occupied by integers? Is the whole also an object? Why is memory not being released at all? Just the whole cannot be stated? Or swim and string? References to objects also?
  • Why is there -7 MB for memory? Is it because a list implemented as a list of arrays is freed from the heap?
  • whether it is a list or a dict, del x can only free the data structure (what I mean is that the structure of the array list or the dict structure), but integers, references to objects can be marked as free, but did not return to system?

And how am I or if there is a way to free all underscores in x in this example?

 Line # Mem usage Increment Line Contents ================================================ 4 28.047 MiB 0.000 MiB @profile 5 def function(): 6 248.008 MiB 219.961 MiB x = [list(range(10)) for _ in xrange(1000000)] 7 502.195 MiB 254.188 MiB y = copy.deepcopy(x) 8 494.562 MiB -7.633 MiB del x[:] 9 494.562 MiB 0.000 MiB return y 
+5
source share
1 answer

TL DR

del does not free variables, as in C, it just says that you no longer need it. Then comes a detailed description of the implementation.

Rational

So what happens here is that del does not free memory, it just tells python what you did with the variable. In particular:

7.5. Statement del

del_stmt :: = "del" target_list

An exception is recursively defined very similar to how an assignment is defined. Below are some tips.

Deleting a target list recursively deletes each target from left to right.

Deleting a name removes the binding of that name from a local or global namespace , depending on whether the name occurs in a global expression in the same code block. If the name is unbound, a NameError exception will be thrown.

Removing links to attributes, subscriptions, and sections is passed to the main object; deleting a section is generally equivalent to assigning an empty fragment of the correct type (but even this is determined by the truncated object).

Please note that memory deallocation is not mentioned. Instead, what happens is that you tell python that it can do "anything" with that memory. In this case, your python implementation (I assume it is CPython) saves memory for later use in the memory cache. This allows python to work faster without allocating as much memory later.

Example

Consider this example, where we are del x , and then create a copy of y again. Please note that the amount of memory allocated during the second copy is less than during the first. This is because the memory is reused. If we do this again, we will see that almost any memory is not allocated during the third copy, because python simply reuses the previously allocated memory:

 Line # Mem usage Increment Line Contents ================================================ 4 34.777 MiB 0.000 MiB @profile 5 def function(): 6 37.504 MiB 2.727 MiB x = [list(range(10)) for _ in xrange(10000)] 7 40.773 MiB 3.270 MiB y = copy.deepcopy(x) 8 40.773 MiB 0.000 MiB del x 9 41.820 MiB 1.047 MiB y2 = copy.deepcopy(y) 10 41.820 MiB 0.000 MiB del y2 11 41.824 MiB 0.004 MiB y3 = copy.deepcopy(y) 12 41.824 MiB 0.000 MiB return y 

Sources

Great Blog: http://www.evanjones.ca/memoryallocator/

http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm

0
source

Source: https://habr.com/ru/post/1270879/


All Articles