内存池原理说明
问题
主要有两个问题
内存申请与释放所引起的性能损失问题
c的malloc/free,c++的new/delete
这类内存申请与释放涉及到以下问题
申请时寻找合适的内存块,根据不同的算法有不同的方案
- 分配不小于申请时大小
- 分配能分配的最大内存块
- 分配最接近申请内存大小的内存块
进一步分割内存块到合适大小
释放时对内存进行整理,例如
- 合并连续内存块
- 多线程问题
综上,调用库中的内存分配函数,本身就相对复杂,
可见,如果应用程序频繁地在堆上分配和释放内存,
在比较恶劣的情况下会极大的拖慢程序,进而导致性能的损失。
内存碎片问题
上面说到的频繁内存申请与释放除了本身运行会很耗时之外
还会引起内存碎片问题。
即
连续的内存空间被分割不同大小的内存分割出去,内存空间不再连续,而是碎片化的
假如这时再申请一块内存,尽管剩余内存的总和可能大于所要分配的内存大小,
但系统就找不到连续的内存,也就是足够大的内存块,所以导致分配错误。
原理
内存池技术是一种应用程序自己对内存管理的方案,
又可叫批发零售模型(不确定),一般有以下特性
提前申请
在程序真正申请必要的内存之前,提前申请一块大的内存,
所有的程序需要的内存从这块内存中二次分配。
直到该大内存不足时再去再系统申请,
减少内存申请的次数
大小固定
两部分
- 向系统申请的大块内存大小是固定的
- 大块内存中二次分配的内存也是按固定大小的小块管理
在调用内存分配函数的时候,大部分时间所分配的内存大小都是一定的,
所以可以采用每次都分配固定大小的内存块,这样就避免了内存碎片产生的可能。
重复利用
重复如字面意思,在大块内存二次分配出去的小块内存释放时并不是真的调用free/delete释放
而是使用内存池的管理,将其重新标记为可二次分配,等待再次内存池分配出去利用
只有当一整块的大块内存都处于空闲时才释放给操作系统
减少内存释放的次数
结尾
通过以上说明,与系统管理内存相比,特别是涉及到频繁内存申请与释放的时候
内存池的操作非常迅速,它在性能优化方面的优点主要如下
- 针对特殊情况,例如需要频繁分配释放固定大小的内存对象时,不需要复杂的分配算法和多线程保护。也不需要维护内存空闲表的额外开销,从而获得较高的性能。
- 由于开辟一定数量的连续内存空间作为内存池块,因而一定程度上提高了程序局部性,提升了程序性能。
- 比较容易控制页边界对齐和内存字节对齐,没有内存碎片的问题。
这里涉及到简单内存的理论说明
下面几篇文章有更详实的讨论以及简单c++线程池实现例子