google.tcmalloc 要点

线程缓存(thread cache)

加锁(locking)

加锁的开销是比较大的(cpu要同步 cache),一般要几十个时钟周期,特别是 cpu 较多的时候,锁冲突概率大大增加。

malloc

不是在进入malloc就马上加锁,而是在 thread cache 耗尽后才加锁(用于从全局堆获取内存),加锁的频率被大大降低(通常情况下是几百倍)。

free

不是在每次 free 时都加锁,而是在 free 导致 local cache 空闲出整页内存时,才加锁将内存页交还给全局堆(global heap)

radix-tree

tcmalloc 使用的核心数据结构是radix-tree ,这是trie-tree 的一个变种。tcmalloc 中的radix-tree更是大幅简化,相当于多层页表,32 位环境下是 2 层,64 位环境下是 3 。这样,对一个指针的查找可以在O(1)
的时间内完成,并且可以查找范围(在合并内存页时是必须的)。

Hash 也是O(1),但是Hash不能按范围查找,再加上其它一些缺陷(hash 冲突、rehashO(1) 的常数项也较大等)hash 不适合tcmalloc

按尺寸分组

对小于一定尺寸(32K) malloc,每种尺寸在一些连续的内存页上分配。这被称为size-class,每种尺寸并不是完全等距的,请求的尺寸会按一定规则对齐到下一个size-class

使用size-classmalloc 出的内存就不需要在相邻的内存上(紧邻在malloc出来的内存之前)做簿记(book keeping) 了。传统的malloc需要这样的簿记,以便free时能找到链接的块,并且得到正确的内存大小。

使用 size-class 不但可以省掉额外的内存消耗,并且,可以 size-class对齐

malloc时,按请求的尺寸查找 相应的size-class,如果大于max-size-class32k),就直接从全局堆分配,并且总是页对齐的。

free时,在radix-tree中查找free的内存地址,得到其所属的spanspan就是一块连续多个页的内存),进而得到其它信息(如size-class等,如果是大块内存则直接从全局堆free)。对于小块内存,大多数情况下,剩下的事情就是一个简单的链表操作。如果这次free导致整个span空闲,就将span回收。

总结

tcmalloc 的巨大优势:

  • 线程缓存,大幅减少了加锁,更有效利用cpu cache
  • 使用size-class,减少了小块内存的book-keeping,并且能更好地对齐。
  • 总的开销更低

其他相关文档

http://code.google.com/p/google-perftools/
General Information and Documentation
tcmalloc.html documentation in Chinese (against perftools 0.94)

作者:
该日志由 rockeet 于2010年02月22日发表在C++分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
转载请注明: google.tcmalloc 要点
标签:
【上一篇】
【下一篇】

您可能感兴趣的文章:

发表评论

您必须 登录 后才能发表评论。