程序员都应该了解:为什么要自定义内存malloc( 二 )


何时使用它:需要保留所有大小相同的短期分配池时 。
2)线性分配器/Line Allocator
程序员都应该了解:为什么要自定义内存malloc文章插图
线性分配器(有时称为凹凸分配器)是最简单 , 最有用的自定义分配器之一 。 简短的版本:给定一块内存 , 从头开始 , 然后一个接一个地分配 。 完成所有分配后 , 释放或重用该块 。 一般来说 , 还需要处理对齐 , 溢出和内存不足的问题 , 但是这些都不是特别复杂 。 当需要暂存器来构建临时数据结构 , 或者知道要分配的所有数据都具有有限的寿命时 , 线性分配器非常有用 。 比如说在GUI中处理用户输入事件或游戏中的框架的场景时 , 此方法效果很好 。 最终 , 数据不仅可以很好地存储在CPU缓存中 , 而且分配的实际成本只是一点点算术 , 并且释放基本上是免费(快)的!
何时使用:需要有限寿命的快速临时存储时 。
3)区域分配器/Zone Allocator
程序员都应该了解:为什么要自定义内存malloc文章插图
区域分配器(有时称为“竞技场”分配器)通过放宽前期内存分配来使线性分配器更加灵活 。 可以创建一系列线性分配器 , 而不是单个内存块 。 每当一个空间用完时 , 分配另一个块并切换到该块 。 然后 , 要做的就是保存分配的块的列表 , 以便在完成区域操作后可以将其释放(或返回到池中) 。
区域分配器简单地扩展为线程安全的分配器 。 除了一个线性分配器 , 还可以根据需要在每个线程中分配一个 。 只有区域的线性分配器共享的块列表才需要由互斥锁保护 。
何时使用它:需要具有有限使用寿命的快速临时存储 , 但不知道需要多少存储空间时 。
4)伙伴块分配器伙伴块分配器是最高级的分配器 。 这是非常通用的 。 另一方面 , 它并不特别复杂 , 而我自己的实现仅200 sloc 。 基本思想是 , 从要拆分的大内存块开始 , 进行分配时 , 递归地将内存块分成两半 , 直到拥有所需的大小为止 。 由于子块总是分成几对(伙伴) , 因此只需一点数学就很容易找出任何给定块的伙伴的位置 。 释放一个块时 , 可以轻易地检查伙伴是否空闲 , 然后将它们重新组合成一个更大的块 。
何时使用它:当需要具有可预测性能的通用分配器时 。