stl第二级空间配置器详解(1)
SGI STL考虑到小型内存区块的碎片问题,设计了双层级配置器,第一级配置直接使用malloc()和free();第二级配置器则视情况采用不同的策略,当配置区大于128bytes时,直接调用第一级配置器;当配置区块小于128bytes时,遍不借助第一级配置器,而使用一个memory pool来实现。究竟是使用第一级配置器还是第二级配置器,由一个宏定义来控制。SGI中默认使用第二级配置器。
第一级配置器实现的比较简单,调用malloc()申请内存,申请失败的时候,将抛出bad_alloc异常。下边我着重介绍下二级配置器的实现思路。
上边提到了第二级配置器视情况不同而采用不同的策略;其主要目的是避免太多小额区块造成内存的碎片。通常情况下,当配置区大于128bytes时,配置器视之为“足够大”而直接调用一级配置器,当配置区块小于128bytes时,就以内存池来管理,具体做法是:
sgi二级配置器会将任何小额区块的内存需求量上调至8的倍数,(例如需求是30bytes,则自动调整为32bytes),并且在它内部会维护16个free-list, 各自管理大小分别为8, 16, 24,…,128bytes的小额区块,这样当有小额内存配置需求时,直接从对应的free list中拔出对应大小的内存(8的倍数);当客户端归还内存时,将根据归还内存块的大小,将需要归还的内存插入到对应free list的最顶端。如下图:

图1
那么什么是free-list呢?
首先我们看下free-list的定义
上边free-list节点定义得非常巧妙,与普通链表节点采用struct不同,这里采用的是union;主要原因是由于为了维护free-list链表,每个节点需要额外的指针(指向下一个节点),这样就会造成一种内存浪费。为了避免这种负担,所以采用的union,根据union的特点,从第一个字段看,obj可以看作一个指针,指向链表中的下一个节点;从第二个字段看,obj也可以视为一个指针,不过是指向实际的内存区,如图1所示,这种一物两用的结果,就是不会为了维护链表所必须的指针而造成内存浪费。(因为stl容器是保存对象的,所以其自身信息当然要求是尽可能的少占用内存)。
下边我们根据一个图来讲下第二级空间配置器分配及归还内存区块的过程:
内存分配:

图2
如上,我们要申请96bytes的内存(由于其内部有自动调整机制,所以有可能89~95bytes的申请也会自动上调到96bytes), 首先确定需要在第几号free-list中获取,如图示是第11号free-list my_free_list,然后获取这个第一个元素(即第一块内存)的地址赋值给result,再调整my_free_list让其指向下一个区块。
内存归还:
图3
跟配置内存类似,同样是先寻找对应的free list,然后将要归还的内存块插入到对应free list的头部。
不过在内存配置的过程中,我们还需要处理这种情况:当对应free list没有可用区块时,就需要给对应的free list重新填充内存。如下图:

图4
//传回一个大小为 n的对象,并且有时候会为适当的freelist增加节点.
//假设 n已经适当上调至 8的倍数。
template <bool threads, int inst>
void* __default_alloc_template<threads, inst>::refill(size_t n)
{
int nobjs = 20;
// 呼叫 chunk_alloc(),尝试取得 nobjs个区块做为 free list的新节点。
// 注意参数 nobjs是pass by reference。
char * chunk =chunk_alloc(n, nobjs);
obj * volatile * my_free_list;
obj * result;
obj * current_obj, * next_obj;
int i;
第 2 章空间配置器(allocator)
// 如果只获得一个区块,这个区块就拨给呼叫者用,free list无新节点。
if (1 == nobjs) return(chunk);
// 否则准备调整 free list,纳入新节点。
my_free_list = free_list + FREELIST_INDEX(n);
// 以下在 chunk空间内建立freelist
result = (obj *)chunk; //这一块准备传回给客端
// 以下导引 free list指向新配置的空间(取自记忆池)
*my_free_list = next_obj = (obj *)(chunk + n);
// 以下将 free list 的各节点串接起来。
for (i = 1; ; i++) {//从 1 开始,因为第 0 个将传回给客端
current_obj = next_obj;
next_obj = (obj *)((char *)next_obj + n);
if (nobjs - 1 == i) {
current_obj -> free_list_link = 0;
break;
} else {
current_obj -> free_list_link = next_obj;
}
}
return(result);
}
refill()函数完成的主要功能是:根据所需要申请的区块的大小n,调用chunk_alloc(n, nobjs); 默认申请nobjs个区块(默认为20,又可能不足20,nobjs是引用传递);如果申请的区块只有一个,那么直接返回,free list仍旧无可用区块,如果大于1,那么将第一个chunk块作为返回值,其余的chunk按照n划分为free list的节点,并将其串接到free list中区。最后free list头节点会指向到新分配的chunk。
综上,我便将stl二级空间配置的空间的配置,回收,以及重新填充大小详细介绍了一遍,下篇将继续介绍内存池的设计。
stl第二级空间配置器详解(1)的更多相关文章
- STL源代码分析--第二级空间配置器
本文解说SGI STL空间配置器的第二级配置器. 相比第一级配置器,第二级配置器多了一些机制,避免小额区块造成内存的碎片.不不过碎片的问题,配置时的额外负担也是一个大问题.由于区块越小,额外负担所占的 ...
- stl中的空间配置器
一般我们习惯的c++内存配置如下 class Foo { ... }; Foo* pf = new Foo; delete pf; 这里的new实际上分为两部分执行.首先是先用::operator n ...
- STL源码分析读书笔记--第二章--空间配置器(allocator)
声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...
- C++ STL学习之 空间配置器(allocator)
众所周知,一般情况下,一个程序包括数据结构和相应的算法,而数据结构作为存储数据的组织形式,与内存空间有着密切的联系. 在C++ STL中,空间配置器便是用来实现内存空间(一般是内存,也可以是硬盘等空间 ...
- STL——模拟实现空间配置器
目录 问题 SGI版本空间配置器-std::alloc 一级空间配置器 二级空间配置器 Refill.chunkAlloc函数 最后,配置器封装的simple_alloc接口 问题 我们在日常编写C+ ...
- STL源码剖析(空间配置器)
前言 在STL中,容器的定义中都带一个模板参数,如vector template <class T, class Alloc = alloc> class vector {...} 其中第 ...
- STL之空间配置器
在前面很多随笔里都有提到new对象是先分配内存然后初始化对象,主要是对operator new和placement new的使用 在SGI STL中内存的分配和初始化是分开的,分配内存是使用类模板,模 ...
- stl空间配置器alloc
new运算包含两阶段操作: 1) 调用::operator new分配内存 2) 调用构造函数构造对象内容 delete运算包含两阶段操作: 1)调用析构函数将对象析构 2)调用::op ...
- [stl] SGI STL的空间配置器
第一级空间配置器 第一级配置以malloc(), free(), realloc()等c函数执行实际的内存配置,释放.重配置操作,并实现出类似c++ new handler的机制.它不能直接使用c++ ...
随机推荐
- 深入理解Java类加载器(3)
5.2 网络类加载器 下面将通过一个网络类加载器来说明如何通过类加载器来实现组件的动态更新.即基本的场景是:Java 字节代码(.class)文件存放在服务器上,客户端通过网络的方式获取字节代码并执行 ...
- AWS EC2安装docker时的问题
在AWS EC2的实例(Ubuntu)里面安装docker时,使用通常的安装步骤 :~$ sudo apt-get update :~$ sudo apt-get install docker 安装完 ...
- dbms_sqltune.report_sql_monitor 自动调优
--创建 dbms_sqltune.create_tuning_task ; --执行 dbms_sqltune.execute_tuning_task; --产看创建的task 和 status S ...
- C# 字符串多行显示、文本换行
以textbox为例 ①:先设置textbox的属性Multiline为true ②:组织好显示字符串:FistLine(第一行要显示的字符).SecondLine(第二行要显示的字符)....... ...
- js仿QQ拖拽删除
原生js实现仿QQ拖拽删除交互,无需任何依赖. 项目演示请看这里, gitHub请移步这里. 由于源码很长,所以贴到最下面了. 效果截图如下: 核心思想呢,就是点击圆点的时候全屏覆盖个canvas,在 ...
- 【刷题】BZOJ 1969 [Ahoi2005]LANE 航线规划
Description 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系--一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel ...
- BZOJ 2426: [HAOI2010]工厂选址
2426: [HAOI2010]工厂选址 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 364 Solved: 248[Submit][Status ...
- BZOJ 1180: [CROATIAN2009]OTOCI
1180: [CROATIAN2009]OTOCI Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 989 Solved: 611[Submit][S ...
- 遇到问题----mongodb-----mongorestore报错too many open files甚至mongo服务崩溃
之前运行mongorestore还原mongodb数据库一直都没问题,今天还原的时候 报错too many open files.而且mongo服务经常崩溃需要重启. 问题有两方面: 原因一 一个原因 ...
- JS的异步
1.异步 程序中现在运行的部分和将来运行的部分之间的关系是异步编程的核心. 多数JavaScript开发者从来没有认真思考过自己程序中的异步到底是如何出现的,以及为什么会出现,也没有探索过处理异步的其 ...