SGI STL memory pool

Reprinted: http://www.cppblog.com/kevinlynx/archive/2008/06/12/53054.html
Various containers in stl have an optional template parameter: allocator, which is a component responsible for memory allocation. The allcator specified by the STL standard
is defined in the memory file. The allocator specified by the STL standard simply encapsulates operator new, which is a bit disappointing in efficiency.

In the STL implemented by SGI, all containers use the allocator defined by SGI itself. This allocator implements a small object memory pool.
In order to handle the memory allocation of small objects in Loki, a similar memory management mechanism is also implemented.

Roughly speaking, the memory pool is to obtain memory from the system in large chunks, and then divide it into many small chunks and link them in the form of a linked list.
There are many different types of linked lists inside , and different linked lists maintain memory blocks of different sizes. Every time the client requests to allocate memory, allcator
finds the corresponding linked list (the closest size) according to the requested size, and then removes the memory from the linked list. When the client returns the memory, the allocator puts this memory
back into the corresponding linked list.

I simply drew a picture to show the entire structure:
Insert picture description here
Allocator maintains a linked list array internally, and all array elements are pointers to the head of the linked list. Each node of linked list A maintains an 8bytes memory block, and
each node of linked list B maintains a 16bytes memory block.

When the client requests to allocate 10bytes of memory, the allocator adjusts 10 to the nearest 16bytes (only greater than 10bytes), and then finds that
there is an available memory block in the 16bytes linked list (linked list B), so it takes out a piece of memory from B and returns. When the client returns, the allocator finds the corresponding linked list and puts the
memory back into linked list B.

The general process is as simple as that. Some people may say that if you use a linked list to maintain a piece of memory, the linked list itself will waste some memory (when I contacted the memory pool a long time ago, I
always saw similar arguments ==|), in fact, through some simple The trick is completely avoidable. For example, here allocator maintains a lot of memory blocks,
anyway, these memory itself is idle, so we can directly record the information (next element) of the linked list in these memory.
Still write some code to elaborate on this little trick:

struct Obj
    {
        Obj *next;
    }; 

    void *mem = malloc( 100 );
    Obj *header = (Obj*) mem;
    Obj *cur_obj = header;
    Obj *next_obj = cur_obj;
    for( int i = 0; ; ++ i )
    {
        cur_obj = next_obj;
        next_obj = (Obj*)((char*)next_obj + 10 );
        if( i == 9 )
        {
            cur_obj->next = 0;
            break;
        }
        else
        {
            cur_obj->next = next_obj;
        }
    }
    free( mem );

In this way, through the header pointer and the next field, the memory pointed to by mem can be accessed block by block (here 10byts), and the nodes of these linked lists
are directly stored in this memory, so there is no additional consumption at all.

I used C to imitate the allocator of SGI and wrote a configurable memory pool, on which an allocator was packaged in accordance with the STL standard, which can be directly
used in the STL that comes with VC. The test code was tested a bit and found that there are obvious gaps on different machines.

Guess you like

Origin blog.csdn.net/qq_33898609/article/details/115007267