Parse freeblock in Python from Python source code
This article describes how to parse freeblock in Python from Python source code, including memory space allocation and other knowledge. For more information, see
1 Introduction
In python memory management, there is a block concept. It is similar to the SGI subspace configurator.
First, apply for a large space (4 kb), and then cut it into a small portion (8, 16 to 512 ).
When there is a request for memory application, the simple process is: Find the corresponding block based on the size, and then give it a copy on freeblock.
2 Problems
The entire process is a natural slab allocation method. But when I read this code, I am confused:
?
1 2 3 4 5 6 7 8 9 |
Static void * _ PyObject_Malloc (void * ctx, size_t nbytes) { ... Pool-> freeblock = (block *) pool + pool-> nextoffset; Pool-> nextoffset + = INDEX2SIZE (size ); * (Block **) (pool-> freeblock) = NULL; // [1] ... } |
Freeblock points to an idle linked list, which is easy to understand. But why should I add code 1!
A child shoes familiar with C can easily see its function. It is assigning a value of NULL to * freeblock.
But why?
Until you see the memory recycle code:
?
1 2 3 4 5 6 7 |
Static void _ PyObject_Free (void * ctx, void * p) { ... * (Block **) p = lastfree = pool-> freeblock; Pool-> freeblock = (block *) p; ... } |
Recall that the SGI sub-space configuration requires a linked list pointing to available small blocks in the block. Because these are fast and discrete, only pointers can be used to index them.
In the SGI subspace configuration, a union is used to save space: when there is data, it stores real data; when there is no data, it becomes a pointer to the next available memory:
?
1 2 3 4 |
Union _ Obj { Union _ Obj * free_list_link; Char client_data []; }; |
In this way, the problem becomes obvious. Freeblock points to a linked list. The next field of the linked list is indexed by itself.
In _ PyObject_Free, memory p is to be recycled. It should be inserted in the freeblock linked list header, and freeblock is updated to it. At the same time, p points to the content that the original freeblock points to, which is a very simple chain table insert operation.
In this way, we can use freeblock = * freeblock to work during traversal.
As shown in: