内存池

内存池原理说明

本文是对网上看到的几份相关文档的简单总结

问题

主要有两个问题

内存申请与释放所引起的性能损失问题

c的malloc/free,c++的new/delete
这类内存申请与释放涉及到以下问题

  1. 申请时寻找合适的内存块,根据不同的算法有不同的方案

    • 分配不小于申请时大小
    • 分配能分配的最大内存块
    • 分配最接近申请内存大小的内存块
  2. 进一步分割内存块到合适大小

  3. 释放时对内存进行整理,例如

    • 合并连续内存块
  4. 多线程问题

综上,调用库中的内存分配函数,本身就相对复杂,
可见,如果应用程序频繁地在堆上分配和释放内存,
在比较恶劣的情况下会极大的拖慢程序,进而导致性能的损失。

内存碎片问题

上面说到的频繁内存申请与释放除了本身运行会很耗时之外
还会引起内存碎片问题。

连续的内存空间被分割不同大小的内存分割出去,内存空间不再连续,而是碎片化的
假如这时再申请一块内存,尽管剩余内存的总和可能大于所要分配的内存大小,
但系统就找不到连续的内存,也就是足够大的内存块,所以导致分配错误。

原理

内存池技术是一种应用程序自己对内存管理的方案,
又可叫批发零售模型(不确定),一般有以下特性

提前申请

在程序真正申请必要的内存之前,提前申请一块大的内存,
所有的程序需要的内存从这块内存中二次分配。
直到该大内存不足时再去再系统申请,
减少内存申请的次数

大小固定

两部分

  • 向系统申请的大块内存大小是固定的
  • 大块内存中二次分配的内存也是按固定大小的小块管理

在调用内存分配函数的时候,大部分时间所分配的内存大小都是一定的,
所以可以采用每次都分配固定大小的内存块,这样就避免了内存碎片产生的可能。

重复利用

重复如字面意思,在大块内存二次分配出去的小块内存释放时并不是真的调用free/delete释放
而是使用内存池的管理,将其重新标记为可二次分配,等待再次内存池分配出去利用
只有当一整块的大块内存都处于空闲时才释放给操作系统
减少内存释放的次数

结尾

通过以上说明,与系统管理内存相比,特别是涉及到频繁内存申请与释放的时候
内存池的操作非常迅速,它在性能优化方面的优点主要如下

  1. 针对特殊情况,例如需要频繁分配释放固定大小的内存对象时,不需要复杂的分配算法和多线程保护。也不需要维护内存空闲表的额外开销,从而获得较高的性能。
  2. 由于开辟一定数量的连续内存空间作为内存池块,因而一定程度上提高了程序局部性,提升了程序性能。
  3. 比较容易控制页边界对齐和内存字节对齐,没有内存碎片的问题。

这里涉及到简单内存的理论说明
下面几篇文章有更详实的讨论以及简单c++线程池实现例子