小对象分配技术是Loki提高效率的有效途径,Loki里广泛使用小对象, 如果使用系统默认分配器,因为薄记得缘故,可能代价在400%以上,所以这个是必须要解决的问题。我们首先来谈Chunks。
1.MemControlBlock结构







是的,你看到了,这里没有块大小标志,这个时候注意这点会对你理解Chunk代码很有帮助,因为MemControlBlock里没有保存块大小的字段,所以它的上层——Chunk必须每次在需要的时候传入,而且必须自己保证不会修改传递数字的大小,这是非常基础的假设,宛如二者是一个类,是一个整体,你不能进行自己给自己错误数据的方式进行测试,那肯定是极端疯狂者的做法或者有特殊原因。
明白了这点,在Chunk的代码中关于size_t的意义就非常好理解了。
2.Chunks结构











我希望可以在声明上花多一点时间,这有助于你理解系统,从这个角度来说代码片段是没有任何意义的。
Init初始化本Chunk,它有若干MemControlBlock组成,你要指定块数量和块大小,特别要注意的是,如我们上边讨论的,一旦调用成功,你必须保证blockSize的大小每次都一样(永远不改变)。可以预期的是,在Init函数里使用了new方法开辟大块内存,以后每次Allocate都是回传特定一块。
对,还有一点要注意,基于Chunk的内存分配的块大小是在Init中已经确定的,是的,就是我反复强调的blockSize,你无法改变它,使用Allocate分派内存也是这个大小,而且每次一块,从这个层次上来说,这里的内存分配没有任何自由度,你可以认为这是new情况下的char,这是最小的分配单元。
有了以上两点注意,Allocate和Release的功能变的非常简单,取出一块特定大小的内存或归还一块内存。
pData_是Init中new出内存的位置。关于firstAvailableBlock_和blockAvailable_两个数据,是为了高效处理内存Allocate和Deallocate而定义的,使用它们,我们可以避免遍历查找内存块,尽管查找的效率好不错,但是不要忘了我们在做底层基础块,线性复杂度是我们十分不愿意看到的。
3.Chunk实现细节
为了高效查找、分配,我们在分配的时候对各个小块标记偏移位置,未分配的内存可以存放任何数据,所以在每个小块的开始存放偏移量是没有任何问题的,firstAvailableBlock记录第一个可用块,那查找该块的策略就是pData_ + blockSize × firstAvailableBlock,这是索引访问。唯一难理解的是归还内存。
我们知道,firstAvailableBlock指向第一块可用内存(如果有的话),归还的时候,它应该指向我们刚归还的那块,这很好处理firstAvailableBlock × blockSize = pcur - pData_ ,关键是firstAvailableBlock在归还前指向可用内存如何在以后被检索到,是的,这块内存也应该有偏移量记录,我们可以记录该可用内存的索引,也就是那一刻的firstAvailableBlock了,问题变的异常简单。
具体代码不再贴了,核心三个函数的功能已经讲明白了。
我们使用了偏移量(构造索引查询)得方法避免了检索,这是Chunk效率的核心部分,Chunk又是小对象分配技术的核心部分。