内存池是对malloc在堆上申请出来的空间进行的管理!
内存池作用:(内存池要用但不要自己造,要懂他的原理)
避免频繁分配内存(recv之前malloc一块空间,让recv函数来用,这种方式内存会被频繁分配释放和使用,会造成内存碎片化,这样当我们再次申请一块大内存的时候会遇到分配失败的情况。)
内存池:jemalloc,tcmalloc
避免频繁分配与释放方法:
1. 使用链表,每次malloc把块加入到链表中,不释放,调用free的时候直接在结构体里设置一个flag
struct memnode {
void *addr;
int size;
int flag;//1用0free
struct memnode *next;
};
struct memnode *mempool;
void *nmalloc(void) {
search
void *addr = malloc();
struct memnode *node;
ADD(mempool, node);
}
void free(void *addr) {
}
2. 分配固定大小块,第一个分配16字节,第二个分配32字节……第6个分配512字节。直接for循环看当前需要的内存块比谁小,这种方式可以防止到后期链表越来越长的现象。这种是为了避免内存碎片,所以大于512的块就直接malloc就好。(这种方式让我想起了STL的alloc)
3. 感觉就是STL的alloc分配方式了,一个数组里每个元素挂一个内存队列,先查找是否能找到能用的内存,如果能找到就直接从队列里面取出来,如果没有就malloc挂到队列里。释放的时候就把这块内存再挂到队列里。
问题:
? ? ? ? 1. 缺点在于链表查找速度慢(分配的时候查找内存块是否可用,释放的时候查找内存块),解决:可以准备两个集合,一个是用的一个是没用的;查找对应的节点可以使用Hash或者红黑树rbtree
? ? ? ? 2. 出现间隙:相同大小快的内存可能不是分配在一起,这种会造成小块回收的影响,但是对于一个连接对应一个内存池不需要做小块的回收。小块内存回收是一个极其麻烦的事情
内存池使用场景:1.全局内存池(jemalloc/tcmalloc)?2.针对每一个连接fd做一个内存池 3.为每一个消息做一个内存池
|