http://g.oswego.edu/dl/html/malloc.html
doug lea从87年开始写的dynamic memory allocator,到现在一直在发展,历时20+年的进化,成为一些版本的linux的内存分配器,在我见过的一些给力游戏engine中也有应用。
说到dynamic memory allocator,不禁会想到在ubi时候第一个项目,看见当时主程写的dynamic memory allocator,大惊:居然内存分配也要自己写的。里面各种hash,cache,对小内存的特殊处理,还根据游戏的特性专门做一些专区优化等。哈哈,那个项目真是让我印象深刻,看前辈的代码常常会有惊喜:我草,还可以这样写啊。里面的程序员很牛,大家嘻嘻哈哈连打再闹的就把事情完成的非常牛逼,以至于让我觉得做项目就这么简单。
-------------------------
goals
dl提到memory allocator需要在这些goals上取得平衡(清晰的思路我喜欢)
- 兼容性
- 好的移植性
- 空间和时间上的效率
- locality:分配内存时候尽可能保证在空间上相近,来提升cache performance
- 好的可性能测试和debug能力
实际实现中,的确有遇到不少矛盾的地方,一些平衡工作就要做了。
------------------------
算法
- boundary tags:在chunk的首尾都是有size information的,这样就使得两个重要功能成为可能:
- 两个free chunk可以merge起来
- 可以从任意位置开始遍历chunks
- binning:把chunk以size进行分组,以类似hash表的方式表示,以best fit的方式进行分配
------------------------
locality
这个特性与其他的特性比如best fit是有冲突的,所以做一个优先级的排列,如果其他的都满足才会到这个优先级来尽量满足最近分配的东西在内存地址上也是近的。
------------------------
caching
merge和split chunk都是非常耗时的,所以可以做一些事情来降低这个损耗。
- deferred merge,如果刚好free了一个,又alloc一个同样大小的,就免去了一次split和一次merge了
- pre split,不用每一次alloc才split一点,可以在条件满足的情况下,一次split很多
- 一些启发数算法,也就是有条件有规则的猜了,但是这种就是不能在所有情况下达到最好,但是启发数算法是有其存在道理的。
在后面的dlmalloc version中只是针对小size的内存进行caching。