This article describes how to parse freeblock in Python from Python source code, including memory space allocation and other knowledge. if you need it, refer to the following 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:
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:
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:
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: