黑帽联盟

标题: 内存优化总结:ptmalloc、tcmalloc和jemalloc [打印本页]

作者: yun    时间: 2018-5-25 16:10
标题: 内存优化总结:ptmalloc、tcmalloc和jemalloc
概述需求
系统的物理内存是有限的,而对内存的需求是变化的, 程序的动态性越强,内存管理就越重要,选择合适的内存管理算法会带来明显的性能提升。
比如nginx, 它在每个连接accept后会malloc一块内存,作为整个连接生命周期内的内存池。 当HTTP请求到达的时候,又会malloc一块当前请求阶段的内存池, 因此对malloc的分配速度有一定的依赖关系。(而apache的内存池是有父子关系的,请求阶段的内存池会和连接阶段的使用相同的分配器,如果连接内存池释放则请求阶段的子内存池也会自动释放)。

目标
内存管理可以分为三个层次,自底向上分别是:

本文主要介绍了glibc malloc的实现,及其替代品
一个优秀的通用内存分配器应具有以下特性:

现状
目前大部分服务端程序使用glibc提供的malloc/free系列函数,而glibc使用的ptmalloc2在性能上远远弱后于google的tcmalloc和facebook的jemalloc。 而且后两者只需要使用LD_PRELOAD环境变量启动程序即可,甚至并不需要重新编译。
glibc ptmalloc2
ptmalloc2即是我们当前使用的glibc malloc版本。
ptmalloc原理系统调用接口
x86_process_address_space.png
上图是 x86_64 下 Linux 进程的默认地址空间, 对 heap 的操作, 操作系统提供了brk()系统调用,设置了Heap的上边界; 对 mmap 映射区域的操作,操作系 统 供了 mmap()和 munmap()函数。
因为系统调用的代价很高,不可能每次申请内存都从内核分配空间,尤其是对于小内存分配。 而且因为mmap的区域容易被munmap释放,所以一般大内存采用mmap(),小内存使用brk()。

多线程支持
ptmalloc内存管理
ptmalloc分配流程
ptmalloc-alloc-flow.png

ptmalloc的缺陷
tcmalloc
tcmalloc是Google开源的一个内存管理库, 作为glibc malloc的替代品。目前已经在chrome、safari等知名软件中运用。
根据官方测试报告,ptmalloc在一台2.8GHz的P4机器上(对于小对象)执行一次malloc及free大约需要300纳秒。而TCMalloc的版本同样的操作大约只需要50纳秒。

小对象分配
CentralCache分配管理
回收
tcmalloc的改进
性能对比官方测试
测试环境是2.4GHz dual Xeon,开启超线程,redhat9,glibc-2.3.2, 每个线程测试100万个操作。
tcmalloc-perf1.png
上图中可以看到尤其是对于小内存的分配, tcmalloc有非常明显性能优势。
tcmalloc-perf2.png
上图可以看到随着线程数的增加,tcmalloc性能上也有明显的优势,并且相对平稳。
github mysql优化
github使用tcmalloc后,mysql性能提升30%

Jemalloc
jemalloc是facebook推出的, 最早的时候是freebsd的libc malloc实现。 目前在firefox、facebook服务器各种组件中大量使用。

jemalloc原理
jemalloc-arena-chunk.png
上图可以看到每个arena管理的arena chunk结构, 开始的header主要是维护了一个page map(1024个页面关联的对象状态), header下方就是它的页面空间。 Small对象被分到一起, metadata信息存放在起始位置。 large chunk相互独立,它的metadata信息存放在chunk header map中。


jemalloc的优化
性能对比官方测试
jemalloc-throughput.png
上图是服务器吞吐量分别用6个malloc实现的对比数据,可以看到tcmalloc和jemalloc最好(facebook在2011年的测试结果,tcmalloc这里版本较旧)。
4.3.2 mysql优化
测试环境:2x Intel E5/2.2Ghz with 8 real cores per socket,16 real cores, 开启hyper-threading, 总共32个vcpu。 16个table,每个5M row。
OLTP_RO测试包含5个select查询:select_ranges, select_order_ranges, select_distinct_ranges, select_sum_ranges,
jemalloc-mysql-perf.png
可以看到在多核心或者多线程的场景下, jemalloc和tcmalloc带来的tps增加非常明显。


总结
在多线程环境使用tcmalloc和jemalloc效果非常明显。
当线程数量固定,不会频繁创建退出的时候, 可以使用jemalloc;反之使用tcmalloc可能是更好的选择。

作者: yzyl    时间: 2018-6-1 11:53
看上去还不错哦





欢迎光临 黑帽联盟 (https://bbs.cnblackhat.com/) Powered by Discuz! X2.5