ptmalloc(glibc的malloc)是Linux提供的内存分配管理模块,目前我们MySQL默认使用的内存分配模块。

tcmalloc是Google提供的内存分配管理模块。

jemalloc是FreeBSD提供的内存分配管理模块。

 

下面用sysbench对MySQL5.7.18搭配三种不同的内存分配管理模块做了压测。

 

【sysbench配置】

16个tables,单表数据量2500W,OLAP模式,预热时间600S,单次测试时间600S,每个场景测试5次。

 

【mysql配置】

关闭预热,buffer pool调整为16G,服务器物理内存64G

innodb_buffer_pool_load_at_startup=0

innodb_buffer_pool_size=16G

【测试数据】

QPS ptmalloc2 tcmalloc4.1.0 jemalloc-5.0.1
warm up 8158.05 8720.78 8828.06
Threads 16 8788.19 8755.96 9976.9
Threads 32 13481.61 11908.99 13559.32
Threads 64 15722.35 15678.27 17015.05
Threads 128 17957.68 17929.17 19665.71

 

TPS ptmalloc2 tcmalloc4.1.0 jemalloc-5.0.1
warm up 453.22 484.47 490.44
Threads 16 488.21 486.43 554.25
Threads 32 748.96 661.59 753.28
Threads 64 873.43 870.99 945.24
Threads 128 997.57 996.02 1092.42

 

ptmalloc tcmalloc jemalloc
VmRSS: 2259272 2325520 2899384
VmRSS: 4942224 4205684 3990556
VmRSS: 7351488 6668696 6585080
VmRSS: 9703240 9031616 9027632
VmRSS: 12005820 11318512 11479836
VmRSS: 14261672 13639416 13845412
VmRSS: 16467972 15919476 16175976
VmRSS: 18358520 18111000 18443324
VmRSS: 18366840 18403856 18649424
VmRSS: 18368820 18404236 18650740
VmRSS: 18368504 18406144 18650896
VmRSS: 18467844 18492448 18718692
VmRSS: 18469004 18492880 18719844
VmRSS: 18469268 18493016 18720412
VmRSS: 18469796 18493568 18721692

 

【图形展示】

 

【结论】

1、jemalloc在多线程高并发环境下,随着并发线程数的增加,QPS和TPS增长比较稳定,性能高于ptmalloc和tcmalloc。

2、在目前的压测场景下,随着线程数的增加,MySQL进程占用的物理内存并没有太大的差异。

3、关于jemalloc的应用,相对tcmalloc而言,jemalloc是MariaDB,Redis等默认的内存分配管理模块,另外AliSQL也集成了jemalloc。

 

【附录】

1、下图是其他机构的一个测试报告(针对较早之前的版本),最左边的是glibc的ptmalloc,最右边的就是jemalloc,

可以看到jemalloc和tcmalloc的性能差异不大,jemalloc的效率稍高。

 

2、三者的比较

ptmalloc2

tcmalloc4.1.0

jemalloc-5.0.1

ptmalloc的缺陷

  • 后分配的内存先释放,因为 ptmalloc 收缩内存是从 top chunk 开始,如果与 top chunk 相邻的 chunk 不能释放, top chunk 以下的 chunk 都无法释放。
  • 多线程锁开销大, 需要避免多线程频繁分配释放。
  • 内存从thread的areana中分配, 内存不能从一个arena移动到另一个arena, 就是说如果多线程使用内存不均衡,容易导致内存的浪费。 比如说线程1使用了300M内存,完成任务后glibc没有释放给操作系统,线程2开始创建了一个新的arena, 但是线程1的300M却不能用了。
  • 每个chunk至少8字节的开销很大
  • 不定期分配长生命周期的内存容易造成内存碎片,不利于回收。 64位系统最好分配32M以上内存,这是使用mmap的阈值。

tcmalloc的改进

  • ThreadCache会阶段性的回收内存到CentralCache里。 解决了ptmalloc2中arena之间不能迁移的问题。
  • Tcmalloc占用更少的额外空间。例如,分配N个8字节对象可能要使用大约8N * 1.01字节的空间。即,多用百分之一的空间。Ptmalloc2使用最少8字节描述一个chunk。
  • 更快。小对象几乎无锁, >32KB的对象从CentralCache中分配使用自旋锁。 并且>32KB对象都是页面对齐分配,多线程的时候应尽量避免频繁分配,否则也会造成自旋锁的竞争和页面对齐造成的浪费。

jemalloc的优化

  • Jmalloc小对象也根据size-class,但是它使用了低地址优先的策略,来降低内存碎片化。
  • Jemalloc大概需要2%的额外开销。
  • Jemalloc和tcmalloc类似的线程本地缓存,避免锁的竞争
  • 相对未使用的页面,优先使用dirty page,提升缓存命中。

发表评论

邮箱地址不会被公开。 必填项已用*标注