5. 第五讲 other issues

 5. 第五讲 other issues
5.1 GNU C++

image-20211208181929620
5.2 GNU C++对allocators的描述

 image-20211208181942134


之所以谈到容器,因为分配器就是为容器服务的。

::operator new继续往下调用的是malloc。

image-20211208181954504

__gnu_cxx::new_allocator和__gnu_cxx::malloc_allocator没有什么特殊的设计,没有内存池的设计,这就是最容易满足需求的做法。
__gnu_cxx::new_allocator相对来说稍微好一些,因为::operator new可重载。

image-20211208182007740
fixed-size pooling cache固定大小的内存池缓存,就是第二讲中提到的16条链表,每条管理不同大小的内存块,内存块都是8的倍数;
cache就是之前提到的先准备一大块内存,然后慢慢划分,最大的优势是去除cookie,同时因为减少了malloc 的调用,速度上有一些提升,但这不应该是最大的优势;
__gnu_cxx::__mt_alloc是多线程的allocator。

 image-20211208182018073


注意测试分配器的三个指标;

image-20211208182028440
C++的数组,是静态的,不是动态的,因此避免了"在运行期添乱、增加开销";
"甚至在program startup 情况下也可使用"的意思是在进入程序员编写的程序main之前(右侧的core dump)就可以使用__gun_cxx::array_allocator了,也就是说还没有准备好动态分配的时候,就已经有__gun_cxx::array_allocator了。不过在VC6下的startup被写成了一个函数mainCRTStartup(),这个函数里的第一个动作就是_heap_init进行内存管理的初始化,除非是在这个动作之前还要做事情,否则"设置在program startup 情况下也可使用"这句话的意义就不大了,因为内存管理的初始化完成后,其他的分配器也可以使用了;


5.3 VS2013 标准分配器与new_allocator

 image-20211208182154525


没有做什么额外操作的分配器。
5.4 G4.9 标准分配器与new_allocator

image-20211208182206754
标准库中的默认分配器,没有做什么额外操作的分配器。
5.5 G4.9 malloc_allocator

 image-20211208182235773


5.6 G4.9 array_allocator

image-20211208182258980
第二模板参数不管是使用std::tr1::array 还是std::array都一样,因为本质相同,底部是一个C++的数组;
C++的数组是静态的,不需要释放,不需要归还,所以array_allocator里面只有allocate() 函数,如果调用deallocate()则是调用的父类的接口,但是这个接口里面do nothing;

 image-20211208182323656


array_allocator<int, array<int, 65536>> myalloc(&my); 调用构造函数,其中myalloc是对象名称;

image-20211208182311808
其中

typedef ARRAY std::array<int, 65536>;
ARRAY* pa = new ARRAY;
1
2
这两行代码等同于上一个图中的int my[65536]; 区别在于,int my[65536]; 是静态数组,而这两行是使用动态分配的方式分配的内存;

5.7 G4.9 debug_allocator

image-20211208182345728
sizeof(size_type)在绝大多数系统中都是4,记录区块的大小;
_S_extra()函数的结果表示额外的内存相当于几个元素;
包裹另一个分配器,让分配的区块还多带extra的空间,用于记录整个区块的大小,扮演的角色类似于cookie;
做内存管理的时候,“阳春”型(什么都没做)是没有用的,真正有用的是设计成内存池,设计成内存池的主要用意是去cookie,也提升了一些效率(减少了malloc的调用次数),去除了cookie,又调用debug_allocator,又包装了一层,这样的意义不大;
5.8 G2.9容器使用的分配器不是 std::allocator 而是 std::alloc

 image-20211208182424167


容器使用的分配器都是std::alloc;

image-20211208182434533
特点:只拿内存却不还,不会影响自己,但是可能会影响其他进程;
5.9 G4.9 __pool_alloc 用例

 image-20211208182506249


真正有用的分配器是这种智能型的分配器,我们追求的是没有cookie。

5.10 G4.9 bitmap_allocator

image-20211208182532557
容器一次都会只要一个元素;
5.10.1 关于blocks,super-blocks,bitmap,mini-vector

 image-20211208182746006


blocks就是客户需要的;
一次性申请 64个blocks 用来后续的供应;
64个blocks + bitmap + use count = super-blocks;
bitmap记录了blocks的使用情况,一个bit位表示1个block,1 表示在手中,0表示给出去,当前的状态是全部都在手中;
use count表示使用了几个block,目前的状态是0个被使用;
block size 是 8 的倍数,8,16,24… 这样的增长,只允许这样的大小,图中假设每个block的size是8,所以super block size = 524 bytes;
__mini_vector中的一个元素表示一个super blocks;

image-20211208182812810
使用了第1个block;
bitmap的变化次序和blocks的变化次序相反,blocks从左往右,bitmap从右往左;
bitmap的最后一个bit变成0;

 image-20211208182833634


分配了第二个block;
bitmap的倒数第二个bit变成0;
use count变成2;

image-20211208182851410
使用了63个blocks;
只有最后一个block没有使用,所以对应bitmap的第一位为1,其他都为0;

 image-20211208182654014


将倒数第三个block归还;
use count变成62;
相对应的bit为变成1010;
5.10.2 1st super-block用罄,启动 2nd super-block

image-20211208182951952
第二个super-block一共有128个blocks,就需要128个bit,即4个整数(每个整数32位);
第二个super-bloc的第1个block给出去了,所以bitmap[0]的最后1个bit变成了0;
标准库中的vector当空间不够的时候会进行 2 倍的增长,此处的_mini_vector就是实现了一个和标准库中的vector相似功能的容器,这里出现了数据的搬动,_M_start此时的值和只有一个元素的时候的_M_start的值是不一样的;
5.10.3 2nd super-block用罄,启动 3rd super-block

 image-20211208183021501


第三个super-block一共有256个blocks,需要256bit来表示每个block被使用的状态,即 8 个整数;
此时_mini_vector需要有第三个单元来控制第三个super-block;
因为_mini_vector是成倍增长的,所以此时有4个单元,但是最后一个单元还没被使用;
每个super-block只为一种value type服务;
图中的蓝色格子,每两格表示一个 entry;
5.10.4 1st super-block 全回收

1st super-block全回收
回收的时候使用了另一个_mini_vector,叫做_S_free_list;
当前的super-block已经是256blocks,因为回收了1st super block,所以下次再分配的时候,分配规模为 128blocks;
回收的vector中只存放64个super-block,如果有第65个super-block回收了,就会归还给O.S;
回收了的super-block要将_mini_vector中的这个entry移除,后面的entry元素要往前推;
5.10.5 2nd super-block 全回收

 image-20211208183133120


5.10.6 3rd super-block 全回收

image-20211208183157443
5.11 使用G4.9 分配器

 image-20211208183226717


最精巧的两个分配器:__pool_alloc和bitmap_allocator

image-20211208183240789
这是测试程序,列举了每个分配器的使用方式。
————————————————
版权声明:本文为CSDN博主「明朗晨光」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011386173/article/details/121872751

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值