GNU C++对allocators的描述
new_allocator 和malloc_allocator,它们都没有特别的动作,无非底部调用operator new和malloc。它们没有用内存池
区别:::operator new是可重载的
智能型的allocator,使用内存池,分一大块然后切分成小块。
这类allocator有bitmap_allocator, pool_allocator, _mt_alloc(multithread多线程的分配器)
第三讲说明了实际malloc也是使用的内存池,因此速度提升不明显,很大的优势是减少了cookie
GNU C++ 提供三种测试,用于测速:插入数据测试,多线程状态下的插入和删除测试,多线程的生产者和消费者模型测试。测速分配器的效率
debug_allocator 不做分配的事情,只是在申请的内存外包一层
VS2013标准分配器&G4.9标准分配器与new_allocator以及G4.9malloc
G4.9array_allocator
指针_M_array指向一个C++数组,分配释放都是对数组的操作,静态数组不需要释放,归还。所以deallocate没做任何事
array_allocator使用例子
G4.9 debug_allocator
debug_allocator是一个包装器,把另一个分配器包装进来,这里是_Alloc分配器,定义为_M_allocator,实际分配的时候就是调用这个分配器的allocate,分配n + extra个大小的空间
第三讲介绍的分配器
在GNU C++4.9版本的__pool_alloc就是上面2.9版本的alloc。它的缺点是什么呢?只拿不还,不把分配的空间还给操作系统
__pool_alloc测试用例
bitmap_allocator
最重要的是_M_allocate_single_object和_M_deallocate_single_object
容器每次请求的都是一个元素的内存分配,所以这里就是单独处理一个object的请求。当不是一个object的时候,就会退化到operator new和operator delete
客户是容器的使用,容器要的一个元素的内存空间就是block,如果是std::list的时候,这个block还包括node里面的指针
上图中一次性挖64个blocks,挖取数量是两倍成长
加上前面的bitmap,还有前面的数值,一起称为super block。
需要64位的bimap,对应blocks数量,来表示每个block的状态。bitmap是unsigned int,一个bitmap是32位,只能记录32个blocks的情况。这里是64个blocks,需要2个bitmap来记录
前面还有一个unsigned int,use count,记录有几个block被分配
最前面还有一个unsigned int,记录super block的大小,记录的大小不包括这个unsigned int本身的大小,是其之后的大小
有一个mini vector(模拟标准库中的vector写出来的)来操纵super block,里面的start指针和finish指针分别指向super block的头和尾
分配内存:下面深灰色这个block被分配出去,use count = 1,然后bitmap[0]最后一位变成0,表示已经分配出去
分配第二个block,下面两个灰色的block表示被分配出去,use count = 2,bitmap[0]后两位变成0,表示这两个block被分配出去
一直分配block出去,已经分配出去63个block,对应的use count = 63,bitmap[1]和bitmap[0]变成80000000H和00000000H,只有最后一个block对应的bitmap中的bit才为1,表示未被分配出去
归还其中一个block,对应的bitmap要变成1,表示未分配(回收回来),然后use count由63变成62
当1个super block(有64个blocks)用完后,开始启用第二号super block,这时候super block中的block块数由64扩大两倍变成128个,由4个bitmap整数表示。
而且mini vector中由一个单元,变成两个单元,每个单元指向一个super block
第二个super block用完(前面已经用完第一个super block,其含有64个blocks,第二个super block包含128个blocks,也已经用完),启用第三个super bloc,其包含的blocks为128 x 2 = 256个。
mini vector中也有第三个单元来控制这个super block
第一个super block全回收,用另一个mini vector(称为free list)中的entry指针指向这个super block,表示已经回收
如果下次新分配一个super block,它其中blocks的数量要减半。前三个superblocks大小分别为64个,128个,256个,由于第一个superblock被回收,那么下次分配的superblock大小由已经分配的最大值256变成一半,为128个blocks
原来的mini vector里面的指向回收的这个superblock头和尾的entry被删除
第二个super block也全回收,则free list里的entry加一个,指向这个super block。
原来的mini vector里面指向这个superblock头尾的entry被删除
第三个super block被全回收,被free list的指针指向