内存池的实现思路

简介: 内存池的实现思路

内存池的目的是避免频繁的申请和释放内存。频繁申请和释放内存会导致内存碎片化,尤其是大量的小块内存的申请和释放。内存池的基本思路是预先分配堆内存,然后接管内存的分配和释放,业务层不断申请和释放内存并不会从系统中频繁分配和释放。


思路一


使用链表组织malloc申请的内存。每个节点保存一个next指针和内存指针,如图:


每次malloc就加入节点,每次释放只是给节点一个标志表示释放。节点结构体如下:

struct memnode {
    void *addr;
    int size;
    int flag; // 1 used, 0 free
    struct memnode *next;
}


每次分配内存先去内存池中查找flag == 0并且有内存块的节点返回而不去系统中去申请。


以上思路是内存池的最基本的实现思路。但是这个思路存在一个问题:


  • 需要的内存不合适则再申请内存,会造成内存越分越小。


解决方法:


节点大小固定方案来解决上面越分越小的问题。但是会造成内存浪费。然后采用分配不同阶梯大小的单元,比如以16个字节为单位: 16, 32, 64, 128, 256, 512, 1024, 2048这种梯度来分配节点大小。比如分配14个字节,这分配16个字节,依次找第一个比需要分配大小的阶梯。这种方案你能解决内存越分越小且避免一定的浪费。如果分配的大小大于最大阶梯的,则直接使用系统申请和释放。此种就引出了大块和小块的内存概念,大块的内存很好处理,不会造成内存碎片化,一般需要处理的是小内存。


思路二


先建立一个哈希表,保存每个阶梯大小。每次分配内存,先查找哈希表及下的内存链表是否有空闲内存,没有这重新分配并加到链表下。释放的时候根据地址去遍历链表找到具体的节点。思路如下图:


内存之间不连续问题需要根据使用场景来判断,比如内存池是使用在一个连接生命周期内,内存池本身都是有生命周期的情况就不需要做小块内存合并处理。当使用全局内存池就需要处理这种问题。


小块内存不连续: 可以预先分配大块内存,然后每次分配都从4K中获取一部分,比如4K,如果4K中所有都不用,则回收。


对于全局内存池,需要回收小块内存,则是一个很麻烦的事情,这种情况下建议使用开源成熟的框架。

开源的有jemalloc/tcmalloc


内存池: 要用,不要自己造,原理一定要懂。


实现参考代码: https://download.csdn.net/download/beichen_yx/86245885



相关文章
|
4月前
3.1.2 内存池的实现与场景分析
3.1.2 内存池的实现与场景分析
|
4月前
理解链表的内存分配
理解链表的内存分配
35 0
|
5月前
|
存储 Java Linux
【高并发内存池】第一篇 项目简介及定长内存池
【高并发内存池】第一篇 项目简介及定长内存池
80 0
|
4月前
|
应用服务中间件 nginx
内存池的实现与分析
内存池的实现与分析
25 0
|
4月前
|
存储 NoSQL 程序员
内存池 - 原理分析(一)
内存池 - 原理分析(一)
|
5月前
|
存储
内存池的实现与场景分析
内存池的实现与场景分析
41 0
|
5月前
|
算法 Linux 应用服务中间件
日常知识点之公开课内存碎片优化(内存池)
日常知识点之公开课内存碎片优化(内存池)
39 0
|
6月前
|
存储 监控 算法
纯C手写内存池
纯C手写内存池
35 0
|
6月前
|
存储 缓存 Linux
万字详解C++内存池:提高内存分配效率的利器(下)
万字详解C++内存池:提高内存分配效率的利器
|
6月前
|
存储 机器学习/深度学习 缓存
万字详解C++内存池:提高内存分配效率的利器(上)
万字详解C++内存池:提高内存分配效率的利器
万字详解C++内存池:提高内存分配效率的利器(上)