之前说道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. C# 6.0新特性(转载)

    简介 VS 2015中已经包含C# 6.0. C#在发布不同版本时,C#总是会有新特性,比如C#3.0中出现LINQ,C#4.0中的动态特性,c#5.0中的异步操作等.. C# 6.0中与增加了不少新 ...

  2. 2014年5月份第2周51Aspx源码发布详情

    Reapter手写分页控件源码  2014-5-12 [VS2010]源码描述:实现repeater控件分页,方便好用,界面设计也很漂亮.数据库是Access,可直接运行.入口是RepeaterTes ...

  3. HDU 3622 Bomb Game(二分+2SAT)

    题意:有一个游戏,有n个回合,每回合可以在指定的2个区域之一放炸弹,炸弹范围是一个圈,要求每回合的炸弹范围没有重合.得分是炸弹半径最小的值.求可以得到的最大分数. 思路:二分+2SAT. 二分炸弹范围 ...

  4. jquery ajax error函数详解

    代码:$(document).ready(function() {            jQuery("#clearCac").click(function() {        ...

  5. VS2010 刷新工具箱(刷新自定义控件)

    有时候自己自定义了控件,定义完后却不见工具箱中刷新出来自定义的控件,解决方案有了三种: 点评:在项目中增加了几个自定义控件,想在窗口上添加时却发现工具箱根本就没有些控件,晕了.记得2008都可以自动出 ...

  6. windows python3.2 shell环境(python叫做解释器)

    [进入python的shell 环境:](python里称作命令解释器,windows叫做cmd,unix叫做shell) cmd  输入set path=%path%;e:\python2.7然后输 ...

  7. java 代码的细节优化

    前言 代码优化,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑 的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用 ...

  8. Java:String和Date、Timestamp之间的转换

    一.String与Date(java.util.Date)互转 1.1 String -> Date String dateStr = "2016-9-28 12:25:55" ...

  9. ssh隧道(端口转发)

    本地转发: ssh -Nf -L [bind_address:]port:host:hostport sshServer -Nf 后台运行 -L 本地转发 [bind_address] 绑定本地地址, ...

  10. 《C与指针》第四章练习

    本章问题 1.Is the following statement legal?If so,what does it do? (下面的语句是否合法,如果合法,它做了什么) 3 * x * x - 4 ...