Malloc技术原理解析以及在转转搜索业务上的实践( 九 )


percpu_arena
启用每个CPU核心的独立内存池 。这可以提高多核系统中的内存分配性能 , 减少了多核之间的锁竞争 。
5.3 压测表现在隔离环境进行服务压测 , 分别对存在较高内存占用的转转搜索排序服务更换3种malloc进行10分钟的多线程压测 , 分析耗时和内存占用表现 。下图从左至右分别是原生malloc tcmalloc jemalloc 压测过程中的内存表现:

Malloc技术原理解析以及在转转搜索业务上的实践

文章插图
图片
下图从左至右分别是原生malloc tcmalloc jemalloc 压测过程中的耗时表现:
Malloc技术原理解析以及在转转搜索业务上的实践

文章插图
图片
根据实践结果可以得出分别使用三种malloc在此服务上进行等条件压测 , 压测过后常驻内存增加了2.51g , 而tcmalloc和jemalloc都只增加了0.5G左右 , 回顾ptmalloc2的内存分配和回收机制 , 有多种原因单一或者同时导致了这一现状:
  • 由于原生的ptmalloc2自身的内存释放机制的不足 , 如果多线程使用内存不均衡 , 容易导致内存的浪费 。比如说线程1使用了300M内存 , 完成任务后glibc没有释放给操作系统 , 线程2开始创建了一个新的arena , 但是线程1的300M却不能使用;
  • 与此同时 , 每个chunk至少需要8字节的开销;
  • top chunk的释放机制收缩内存是从 top chunk 开始 , 如果与 top chunk 相邻的 chunk 不能释放, top chunk 以下的 chunk 都无法释放 。
与此同时 , 在服务初始化完成后 , tcmalloc也拥有更好的内存占用表现 , 可能的原因有:
  • 由于tcmalloc相比jemalloc还需要少一些额外的内存开销;
  • ThreadCache会阶段性的回收内存到CentralCache里来进行分发 , 在初始化阶段线程较少时占用的内存会更低 。
而在耗时分析中 , tcmalloc小幅优于ptmalloc和jemalloc但是差距不大 , 而tcmalloc表现最优可能和线程局部缓存在并发的环境下 , 因为每个线程可以独立地管理自己的内存分配 , 所以减少了线程之间的竞争 , jemalloc在耗时方面表现不佳可能的原因是没有找到更合适的参数 , 还需要进一步的分析和实践 。
5.4 线上表现在线上环境进行对照实验 , 分别对两台内存和cpu占用率一致的物理机上的转转搜索排序服务同时进行重启 , 绿色的是更换tcmalloc的 , 而黄色的是原生的ptmalloc2 , 下图可以观察到服务启动后接入真实流量后内存的变化:
Malloc技术原理解析以及在转转搜索业务上的实践

文章插图
图片
采用原生malloc的物理机上的服务 , 在初始化完成就占用了较多的内存 , 同时随着处理请求的过程 , 内存发生了较大的增长 , 而采用tcmalloc的物理机上的服务 , 则在初始化完成时就有更好的内存占用表现 , 在后续的处理请求的过程内存占用的增量较低 , 且出现了明显的内存释放过程 。
5.5 实践结果在上述的实践后 , 将tcmalloc部署至至搜索推荐的所有服务 , 平均每台机器得到了10g以上的内存减少量 , 经过上文压测和线上的实践得出,选择合理的malloc及其参数对服务的耗时和内存占用表现有着很高的影响 , 耗时情况也保持整体持平 。
6 总结本文主要是结合各类资料梳理了三种linux下常用的malloc:ptmalloc , tcmalloc的整体架构 , 以及对jemalloc的参数讲解 , 概念简介 , 内存分配和回收过程 , 并给出常用的参数的解析说明以及特性分析 , 限于篇幅 , 只对jemalloc进行了参数讲解 , 并分享了上述malloc在转转的搜索排序主服务上的实践经验 , 最终降低了大量的服务器内存占用 , 获得了不错的收益 , 这表明了我们应该根据服务的场景 , 不只考虑于jvm的参数调整 , 还应该选择适当的malloc并调整参数来达到性能和内存占用的平衡 , 不断在技术上精进自己 , 追求卓越 。
7 参考文献
  1. https://zhuanlan.zhihu.com/p/613696274 Linux mmap内存映射;


    推荐阅读