系列文章目录
侯捷 C++内存管理 第一章节 memory primitives 笔记
侯捷 C++内存管理 第二章节 std::allocator 笔记
侯捷 C++内存管理 第三章节 malloc/free 笔记
侯捷 C++内存管理 第四章节 loki::allocator 笔记
文章目录
一、loki的allocator设计
loki::allocator由三个类构成,用户直接操纵SmallObjAllocator。
1. Chunk
(1)Chunk的结构和初始化
Chunk包含三个部分:一个指针和2个unsigned char。
在chunk初始化时会申请一块内存,然后根据Blocksize将内存切成若干块,由一个指针指向该内存。然后遍历这些内存块,把每个内存块的第一个字节按顺序编号,用这种方式实现嵌入式指针的效果。firstAvailableBlock用于记录下一个可以分配的内存块编号,blocksAvailable_用于记录总共还剩多少个内存块可以分配。
(2)Chunk的内存分配过程
找到firstAvailableBlock记录的可分配内存块,该编号为相对于内存开头的偏移量,这块内存的第一位记录的是下一块优先分配的内存编号,在给出这块内存之前,将firstAvailableBlock指针指向次优先级的内存块,同时blocksAvailable_的值-1。
(3)Chunk的内存释放过程
先将firstAvailableBlock写入返回内存块的第一位,再根据返回指针的位置,计算出当前内存块的具体位置编号,赋给firstAvailableBlock,最后将blocksAvailable_的值+1。
2. FixedAllocator
(1)FixedAllocator的结构
FixedAllocator包含一个vector< Chunk >,allocChunk指针指向的是上一个进行内存分配的chunk,deallocChunk指针指向的是上一个进行内存归还的chunk。
(2)Allocator
首先对allocChunk进行判断,若指针为空或者所指的chunk已经满了,则开始从头遍历chunk。
若遍历结束没找到可用的chunk,则再尾部新增加一个chunk,将allocChunk指向新增的chunk,deallocChunk指向第一个chunk。
若遍历过程中找到了可用的chunk,则直接从该chunk进行内存分配,将allocChunk指向该chunk。
(2)Deallocator
Deallocator函数进行两个操作,先找到可以归还内存的chunk,再进行chunk全回收判断。
① VicinityFind
定义两个指针分别指向deallocChunk和deallocChunk + 1的chunk,然后从deallocChunk往front找,deallocChunk + 1往back找,交叉寻找(往上找一个chunk,往下找一个chunk),如果找到内存块所属chunk则进入chunk内存返还,若找不到则一直循环!
② DoDeallocator
先调用Deallocator进行内存回收,回收完了进行判断,若当前chunk可用空间与初始状态不同,则说明还未全回收,直接跳出程序。若相同,则确认全回收,进行返还判断,分为三种情况:
1.若全回收的chunk为vector的最后一块,并且前一块也是全回收的,则将最后一块chunk释放给系统。
2.若全回收的chunk不为vector的最后一块,但最后一块chunk是全回收的,则将最后一块chunk释放给系统,当前chunk不释放。
2.若全回收的chunk不为vector的最后一块,但最后一块chunk也不是全回收的,则将当前chunk移至vector的最后一块。
3. SmallObjAllocator
SmallObjAllocator是由一系列内存块大小不同的vector< Chunk >组成,主要功能是将程序的内存申请分配到合适大小的vector< Chunk >进行处理。
二、loki::allocator的特点
1.结构简单精简,多使用暴力遍历。
2.使用数组取代链表,索引取代指针的特殊实现。
3.有较为简单的chunk全回收判断,进而归还给系统。
4.有deferring(暂缓归还)功能。
5.本身是个allocator,用于分配不带有cookies的内存块,最适用于容器,但底层却通过vector实现,不太合理。