周末看了tcmalloc,明白了大概的情况。 试着记录一下吧。
另一方面,原理tcmalloc是内存定位器,用于管理堆内存,主要影响malloc和free,降低由于频繁分配、内存释放造成的性能损失,有效控制内存碎片。 glibc的内存定位器是ptmalloc2,据说tcmalloc比它快。 一次malloc和free操作,ptmalloc需要300ns,而tcmalloc只需要50ns。 此外,tcmalloc还优化了小对象的存储,需要更少的空间。 tcmalloc特别针对多线程进行了优化,对小对象的指定几乎没有锁定冲突,大对象使用了细粒度高效的自旋锁定(spinlock )。 分配给线程的本地缓存将在长时间空闲时回收,以供其他线程使用。 这样可以在多线程情况下提高内存利用率,避免浪费内存。 ptmalloc2无法做到这一点。
tcmalloc将大、小的对象区别对待。 为每个线程分配一个线程特定的缓存,而线程所需的所有小对象都将分配给该缓存。 因为是thread local,所以基本上没有锁定(如果缓存不足,需要增加内存,则会锁定)。 另外,tcmalloc维持着进程级的高速缓存,所有的大对象都被分配到这个高速缓存,多个线程的大对象的分配从这个高速缓存进行,所以必须锁定访问。 在实际程序中,小对象的分配频率比大对象高得多。 通过这种方式(小对象在未锁定的情况下分配,而大对象在锁定的情况下分配),可以提高整体性能。
线程级cache和进程级cache实际上是多层空闲块列表(Free List )。 一个Free List由大小为k bytes倍数的空闲块分配,包含n个链表,每个链表包含大小为nk bytes的空闲块。 在tcmalloc中,=32KB的对象称为小对象,并且32KB的对象称为大对象。 对于较小的对象,=1024字节的对象以8n字节分配,而1025size=32KB的对象以128n字节分配。 例如,分配20字节返回的空闲块大小为24字节,=1024时最多浪费7字节,1025时最多浪费127字节,而大对象按页面大小4KB排列,最多浪费447字节下图是基本的free list图像。
实际上,free list (我称为空闲块列表)是数组索引中的多个链表,每个链表包含相同大小的块。 可以根据分配的内存大小size计算出合适的块在free list中的下标,并找到对应的空闲块链表。
tcmalloc的数据结构组织如下。
Thread-local free list :线程的本地空闲块cache。 用于分配小对象。
Heap free list :中央free list,全局唯一,每页对齐和分配大对象,或将多个连续页面(称为span )拆分为多个小对象的空闲块
Page array :用于描述当前tcmalloc拥有的内存状态,完成page number到span的映射。
让我们看看小对象的分配。
1 )根据分配的size计算对应的空闲块大小,决定对应的空闲块链表,从thread local的free list进行分配。
)2)的空闲块链接列表不为空时,将开头节点对应的空闲块原样返回,从空闲块链接列表中删除。
)3)如果空闲块链接列表为空,则必须从heap free list获取span。 如果heap free list不为空,请将span拆分为相同大小的空闲块,插入空闲块的链表中,然后返回到第一个节点。
)4) heap free list为空时,调用sbrk或者mmap分配一连串的连续的存储器页面作为span,分割为相同大小的空闲块插入空闲块链接列表,返回头部节点。
分配大对象变得简单。 您只需直接从heap free list中分配4nKB大小的可用块。 如果heap free list中不存在具有该大小的可用块,则系统调用将分配连续的内存页。
tcmalloc还对thread local cache进行垃圾回收,避免内存浪费。
二、tcmalloc的安装和使用为gperftools,安装相对简单,需注意。 64位系统上必须安装lib unwind (仅限此版本,http://download.savannah.GNU.org/releases/lib unwind/lib unwind )。) 包括用于输出堆栈跟踪的API、用于以程序方式轮换堆栈的API以及支持c异常处理机制的API,不需要安装32位系统。 安装过程中可能会发生以下错误:
gcc-d have _ config _ h-I.- I ./include-I ./include/tdep-x86 _ 64-I.- d _ GNU _ soud longjmp.longjmp longjmp.c-fpic-dpic-o setjmp/. libs/longjmp.o/usr/include/x86 _ 64-Linux-GNU/bits/setjmp2. h :2633601:错误: ‘ longjmp ‘ aliasedtoundefinedsymbol ‘ _ longjmp缺少编译选项U_FORTIFY_SOURCE
1、如果未调用configure进行设置,则执行CPP flags=-u _ fortify _ source./configure .时,会自动将编译选项添加到makefile中。
2、已经构成了。 直接修改makefile,找到CPPFLAGS,然后添加-U_FORTIFY_SOURCE。
接下来,安装gperf工具。 这是常规安装就可以了。 缺省情况下安装在/usr/local/lib下,完成后可以调用lddconfig将其添加到动态链接库缓存中以供使用。
使用方法只要在编译时附上tcmalloc动态链接库就很简单了
g test.cpp -ltcmalloc
源代码不需要任何修改。 tcmalloc会自动替换glibc的默认malloc和free。 用简单的命令就可以大大提高性能。 校验谷歌。