为什么需要内存池
- 内存池主要作用是提高分配回收效率,因为每次new delete都要进入到内核,是一个效率相对较低的操作。
- 系统中不用内存池,也不会产生大量的内存碎片
内存池主要是针对频繁分配释放的小块。
我们一次性分配一个大块(如:4K。假设这些小块一定小于4K),以后管理这个大块就行了。
内存池的原理
现在遇到的问题是如何分配这个4K?
第一个是分配,第二个是回收,第三个是扩容。
假设1:
4K - 8bytes = 2K + 1K + 512 + 256 + 128 + 64 + 32 + 16 + 8(伙伴算法)
在回收的时候会出现一种情况,因为可能一个数据使用了两个不连接,这样是可以分配的,但是却无法回收。(回收之后可能需要合并,条件是大小相同的相邻两块都是空闲的,就会合并成一个稍大一些的块))所以小块这种方式以字节为单位来做并不合适,以页为单位比较合适。
比如:4K一页。适合在物理内存的分配与回收。
假设2:
a * 8 + b * 16 + c * 32 + d * 64 + e * 128 + f * 256 = 4K(slab算法)
将4K空间初始划分成多个8bytes,多个16bytes……需要的内存x<8则分配8bytes,8 < x < 16时分配16。假如8bytes的用完了,则将16bytes分成8+8,分一块给它。
伙伴算法
slab算法
slab机制要解决的问题:
- 减少伙伴算法分配小块连续内存时所产生的内部碎片
- 将频繁使用的对象缓存起来,减少分配、初始化、释放对象的时间开销
- 通过着色技术调整对象一更好地使用硬件高速缓存
【注】:
1、如果虚拟内存不断在涨,怎么处理?
(1)内存池是否有内存泄漏(先检查自己写的代码)(使用内存池的时候,会对应的加上打印信息)
(2)如果没有引入内存池,可以采用tcmalloc / jemalloc
解决这种问题
(3)第三方的lib库是否有内存泄漏(这里肯定没有使用我们自己写的内存池)