SGI-STL内存池实现原理
Posted MachineChen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SGI-STL内存池实现原理相关的知识,希望对你有一定的参考价值。
STL之父Alexander Stepanov离开HP之后就去了SGI(Silicon Graphics Computer System, Inc),然后和Matt Austern这些STL大牛一起搞了SGI STL。它也是HP STL的一个继承版本。它属于开放源码,因此你可以修改和销售它。SGI STL被GCC(linux下的C++编译器)所采用,你可以在GCC的Include子目录下找到所有头文件(比如:C:/cygnus/cygwin-b20/include/g++/include)。由于GCC对C++语言标准的支持很好,SGI STL在linux平台上的性能相当出色。此外,其源代码的可读性也很好。可以从如下网站得到更详细的情况介绍:http://www.sgi.com,可以免费下载其源代码。
SGI设计了二级配置机制,第一级配置器直接使用malloc()和free()。当配置区块超过128 bytes时,则采用第一级配置器;否则采用memory pool方式。
memory pool的整体思想是维护128/8 = 16个自由链表,这里的8是小型区块的上调边界。每个自由链表串接的区块大小如下:
序号 | 串连区块大小 | 适用大小 |
---|---|---|
0 | 8 | 1-8 |
1 | 16 | 9-16 |
2 | 24 | 17-24 |
… | … | … |
15 | 128 | 121-128 |
下面这幅图主要是空间配置器的框架:
几个过程的思路:
一、申请过程:
if (用户申请的内存不大于128 bytes)
查找对应的链表
if (对应链表拥有一块以上的区块)
调整链表
返回第一个区块地址
else
准备重新填充链表
向内存池申请内存(指定数量的区块)
if (内存池申请到一个区块)
返回第一个区块地址
else
调整链表,将区块串接起来
返回第一个区块地址
else
直接用malloc()申请内存
二、释放过程:
if (用户释放的内存块大于128 bytes)
直接用free()释放
else
查找对应的链表
回收内存
三、向内存池申请内存过程:
if (内存池空间完全满足需求量)
调整内存池起始位置
返回空间地址
else if (内存池空间不能完全满足需求量,但能提供一个以上的区块)
计算能够提供的最大内存
调整内存池起始位置
返回空间地址
else
从内存池中压缩内存
收集比size大的空间
递归调用,修正nobjs
再次申请内存,可能抛出异常
内存池优缺点:
优点
对于频繁地申请小块内存,减少了申请的时间。
缺点
由于自由链表的内存块大小不连续(8、16、24 …),导致了内部碎片的产生。这使得内存利用率不高。
小块内存释放之后,并没有归还给操作系统,而是放到了自由链表中,会导致系统内存越来越少,除非到程序结束,否则内存不会归还给操作系统。
以上是关于SGI-STL内存池实现原理的主要内容,如果未能解决你的问题,请参考以下文章