C++ memory pool design


1. What is a memory pool? Why use a memory pool?

Once allocated, it is directly called when in use, and the API interface is provided externally, and the application software can directly call the API interface to obtain the required memory space. You can use the memory pool when doing server-side development.

Frequent malloc/free of memory will cause memory fragmentation. Constant malloc and free will also affect performance, because memory operations need to constantly switch between user mode and kernel mode.

Memory data can also be used, why use memory pool?
If the data is pushed to another thread to process business through the message queue, the defined array will not be used. At this point we can use the memory pool to pass pointers in the past.


2. How to implement a memory pool?

We can think of the memory pool as a component that can provide an API interface for others to use.

2.1 Design steps

We can refer to the following steps to design a memory pool:
1) Define the basic data structure of the component first;
2) Define the corresponding function and API provided externally;
3) Give the test function and tell others how to use the API of.

For example: the memory allocation API provided by the memory pool to the application is pmalloc, and the calling form is: void *p = pmalloc(10).

2.2 Memory pool structure

How to define the memory size of each block in the memory pool? How to design so that the memory block in the memory pool is not too small or too large in actual application?
Here, we define according to the size of the memory page. The size of a memory page is 4k, and those smaller than 4k are classified as small blocks of memory, and those larger than 4k are classified as large blocks of memory.
1) Small block memory: < 4k
2) Large block memory: > 4k


small memory structure

struct mp_node_s{
    
    
	unsigned char *start;
	unsigned char* end;
	struct node* next;		//4k使用完后,接入用到下一个4k
	int  flag;				//标识内存是否被使用
}

insert image description here

insert image description here
For example: to apply for 10 bytes, 10 will be allocated from start, and then start will be moved backward by 10 as the new starting position.
When recycling, do not release, use flag to mark.


large memory structure

struct mp_large_s{
    
    
	struct mp_large_s* next;
	void *alloc;
};

Large blocks of memory are processed page by page. When we use a large block of memory, we don't allocate it in advance, but when we use it, we allocate it when there is no free time.
insert image description here
Use the posix_memalign function to apply for a large block of memory, and malloc applies for a small block of memory. They take two different routes. Using malloc to apply for a large block of memory may fail. At this time, we need to use the posix_memalign function to apply for a large block of memory.


memory pool structure

struct mp_pool_s{
    
    
	size_t max;      //大小内存界定值
	struct mp_node_s *current;
	struct mp_large_s *large;
};

//create pool

//destory pool

//pmalloc/palloc

//free


3. Other open source memory pool implementations

Open source memory pools are: tcmalloc/jemalloc
or in nginx: ngx_palloc.c / ngx_palloc.h

Guess you like

Origin blog.csdn.net/locahuang/article/details/120324954