之前说道alloc是原G2.9版本的默认的分配器,这篇就把alloc的原理梳理梳理,顺便简单介绍下有关的内存管理。

  一般而言,我们通常习惯的内存分配操作和释放操作是这样的:

    class Foo {…};

    Foo* p = new Foo;   // 分配内存,然后构造对象

    Delete p;           // 将对象析构, 然后释放内存

  这里的内存分配操作由alloc::allocate()负责, 内存释放操作由alloc::deallocate()负责。

当我们申请的内存很小时,那么new(只是对malloc进行简单的包装)的空间便会形成一定程度的浪费,为什么这么说?我们先来看看基本的内存分配:

       

    (图片来自于侯捷老师的课程《内存管理》,侵删)

  当我们申请10个int对象时,内存分配的空间其实不是10 * 4 = 40个字节这么简单. 如图所示(调试状态下)最上边和最下边的两个cookie(用来记录分配空间的大小)4*2 = 8, 橙色的是Debug状态下申请出的空间帮助Debug,为32 + 4 = 36.而中间部分才为你要申请的10 * 4 = 40个字节,将这些数据加起来40 + 8+36 = 84,而pad那部分则是编译器进行自动补齐,将字节数调整成16的倍数,于是84 + 12 = 96.也就是说你只申请了10个int,而编译器却给你返回96个字节的空间,很神奇是不是?当然重点不是这里,想一下,如果我们只需要申请1个int呢?而上下两个cookie就占了8个字节,是不是很浪费?

  为了考虑小型区块可能造成的浪费及内存破碎问题,SGI设计了双层级分配器,第一级分配器直接使用malloc()和free()。第二级分配器则视情况采取用不同的策略,当分配空间大于128个字节时调用一级分配器,小于128字节时,便采用更复杂的内存池管理方式,也就是alloc。

为了方便管理,SGI第二级分配器会主动将任何小额区块的内存需求量上调至8的倍数(如客端要求30字节,就自动调整为32个字节),并维护16个free-lists,各自管理大小为别为8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128字节的小额区块,free-lists的示意图如下:

  (图片来自于侯捷老师的课程《内存管理》ppt,侵删)

  比如我们申请32字节的空间,然后32 / 8 = 4,即应该落在3号的位置上。alloc内部并不是一次只申请这么多空间。而是一次申请需求的40倍那么大,即40 * 32 = 1280个字节。然后一半存进内存池,另一半切分为20小块, 分一块给客户,剩下的挂在5号元素上。比如再需要申请64个字节,64 / 8 = 8,挂在7号元素上,此时内存池有上次留下的1280 / 2 = 640个字节的空间. 640 / 64 = 10块,分一块给客户,剩下的挂在7号元素上。如图:

  假如当时内存池空间不足时,则再申请 64 * 40 = 2560个字节的空间. 其中一半1280个字节的空间存内存池,剩下的另一半切20个小块,一块分客户,剩下的挂7号元素上面。

  基于这样的原理: 每次申请一大块,慢慢切割来使用,可以减小cookie的不必要的浪费。想象一下,如果申请100万个小额空间,那么省下近800万个字节的空间。也不算小数目了。可谓为了内存利用率,无所不用其极。

然而现在G4.9版本已经不将alloc设置为默认分配器了,原因呢也不清楚。 当然了,这个alloc分配器还是存在的,毕竟这么好的东西。现在它已经在G4.9版本中换了个名字:_pool_alloc(就是内存池的意思嘛),而且也将它置于__gnu_cxx命名空间中,要是我们想用它来当做容器的分配器呢,可以这么使用:

    vector<int, __gnu_cxx::_pool_alloc<int>>   vec;

  当然了alloc内存格局还是非常复杂的,这里我们只是简单了解下它的基本原理。如需了解详情,推荐《STL源码剖析》。相关知识点于第二章---空间置配器(allocator)。

简单来谈谈alloc分配器的更多相关文章

  1. 【bzoj1604】【[Usaco2008 Open]Cow Neighborhoods】简单的谈谈曼哈顿距离

    (最近p站上不去要死了) Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个"群".每只奶牛在吃 ...

  2. G++ 4.4.7 无法编译模板程序,Vs可以,和解?智者尾部留言,本人第一次使用vs pro,通常并且习惯在linux下写些小东西,虽然程序简单;

    vs 模板编译运行Ok \ linux g++ 4.4.7编译模板测试程序,报无法定义 template <typename or class 中的 AnyType> 类型的数据 Exam ...

  3. iOS面试题汇总

    摘要:1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通 ...

  4. 最全的iOS面试题及答案-转载

    1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承:可以实现多个接口,通过实现 ...

  5. 李洪强iOS经典面试题124

    1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通过实现 ...

  6. 超全!iOS 面试题汇总

    之前看了很多面试题,感觉要不是不够就是过于冗余,于是我将网上的一些面试题进行了删减和重排,现在分享给大家.(题目来源于网络,侵删) 1. Object-c的类可以多重继承么?可以实现多个接口么?Cat ...

  7. iOS面试题及答案2015.6.7

    iOS面试题及答案     1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承 ...

  8. linux设备驱动归纳总结(三):6.poll和sellct【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-61749.html linux设备驱动归纳总结(三):6.poll和sellct xxxxxxxxxx ...

  9. iOS 面试题汇总

    1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答: Object-c的类不可以多重继承;可以实现多个接口,通过实现 ...

随机推荐

  1. Visual Studio 编译项目失败,提示找不到文件

     博客地址:http://blog.csdn.net/FoxDave 今天碰到了一个蠢问题,虽然咱们正常情况下是遇不到的,但这确实是个应该注意的地方,所以简单记录一下. Visual Studio ...

  2. JVM-程序编译与代码晚期(运行期)优化

    晚期(运行期)优化 1.为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time,JI ...

  3. Android 微信UI 、点击操作

    上一篇,我们介绍了微信界面的相关知识点.今天我们就来把微信的界面做出来. 首先我们新建一个layout-->LinearLayout-->weixin.xml 我们使用上中下线性布局,采用 ...

  4. Qt msgBox 快捷版

    使用 int iRet = msgBox(pos, tr("警告") , tr("确定要删除当前选中的行吗?") , tr(, ); == iRet) retu ...

  5. Android平板电脑开发— — —碎片

    碎片是一种可以嵌入在活动中的UI片段,它能让程序更加合理与充分地使用大屏幕的空间,碎片通常都是在平板电脑开发中才会使用 简单实例 左碎片布局 <?xml version="1.0&qu ...

  6. Block存储区域

    Block存储区域 首先,需要引入三个名词: ● _NSConcretStackBlock ● _NSConcretGlobalBlock ● _NSConcretMallocBlock 正如它们名字 ...

  7. SpringMVC 用http请求的Get和Post请求作为路由的方法的重载方式

    @Controller @RequestMapping("/messageProcessing") public class WechatPushController { @Aut ...

  8. PAT (Basic Level) Practise:1019. 数字黑洞

    [题目链接] 给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到一个新的数字.一直重复这样做,我们很快会停在有“数字黑洞” ...

  9. js事件处理机制

    一.事件处理程序 a.     DOM0级事件处理程序,被认为是元素的方法. var btn=document.getElementById('myBtn'); btn.onclick=functio ...

  10. 【NOIP2005】过河

    感觉这题好玄--最后看了chty的代码才过,我现在这样必须看题解才能A题怎么办嘛qaq 原题: 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上 ...