对jemalloc的理解

jemalloc 是一款第三方内存分配器,用来替代Linux系统自带的malloc/free,专门解决多线程下内存分配慢、内存碎片多的问题。

先搞懂:malloc是什么

C语言写程序,malloc()申请内存,free()释放内存。

复制代码
char *p = malloc(1024); // 向内存分配器要1024字节内存
free(p);                // 用完还给分配器

malloc不是系统调用!它只是用户态库函数 。 真正向操作系统拿大块内存靠 brk / mmap。

类比: 操作系统 = 大仓库,放着全部物理内存 malloc = 仓库管理员。程序找管理员要一小块内存;管理员不会每次都跑大仓库,自己手里缓存一大块,切小块分给程序。

Linux系统自带默认分配器叫 glibc malloc(ptmalloc2) ,平时写小程序用它没问题;但是高并发多线程程序,它会出两个大麻烦:

  1. 锁竞争严重:多线程同时malloc,要抢一把全局锁,大量线程排队等待,CPU上不去。
  2. 内存碎片:频繁小块申请释放,剩下很多零零碎碎的小空隙,明明空闲内存总和很大,却拿不出一块连续内存;看起来内存占用很高,实际很多是碎片。

碎片类比: 停车场,很多小车停了又开走,留下一堆1‑2个车位的空位。空位总数很多,但是你要停一辆大车,找不到一整块连续位置。这就是内存碎片。

jemalloc就是换一个更聪明的管理员。

jemalloc核心设计思路(小白版)

1. 每个线程有自己的缓存(tcache)

ptmalloc多线程抢同一把锁,排队堵车。

jemalloc:每个线程单独配一个本地小缓存 tcache

  • 线程申请小块内存,优先从自己本地tcache里面拿,不需要抢锁,速度飞快。
  • free释放小块内存,先还给自己线程的tcache,不还给全局。
  • tcache满了,才把一批内存交还给全局;内存不够了再从全局拿一批。

👉 大大减少多线程锁冲突,高并发性能提升非常明显。

2. 分层内存管理:arena 竞技场

jemalloc把内存划分为多个独立区域,叫做 arena。

  • 多个arena互相独立,各自管理自己的内存池,线程分配会绑定到不同arena,减少互相干扰。
  • arena下面再分:huge(大内存)、large(大块)、small(小块)。 小块内存按固定规格对齐:8B、16B、32B ... 512B、1KB、2KB。 比如你malloc(100字节),实际给你128字节的块。用规格化块,分配释放简单,减少碎片。

3. 非常重视减少内存碎片

  • 小块按规格归类管理;
  • 会把连续空闲小块合并;
  • 支持把长期闲置内存归还回操作系统 (真正释放,降低程序RSS内存占用),这个叫 purge(内存回退)。

ptmalloc有时候内存free之后,还留在进程手里不还给操作系统,程序RSS一直居高不下。jemalloc可以主动把空闲内存还给OS。

关键名词简单翻译

  1. tcache:线程本地缓存 每个线程私有,小块内存优先在这里分配,无锁,速度最快。
  2. arena:内存竞技场 多个独立内存池,降低多线程竞争。CPU核多就会生成多个arena。
  3. chunk:向操作系统mmap申请的一大块内存,是arena的原材料。
  4. extent:chunk里面划分出来的连续内存块。
  5. purge:把长时间不用的空闲内存还给操作系统,降低程序占用内存。

和系统glibc‑malloc简单对比

特性 glibc malloc(ptmalloc2) jemalloc
多线程小块分配 全局锁,高并发抢锁卡顿 每个线程tcache本地缓存,几乎无锁
内存碎片 频繁小块业务碎片比较多 碎片控制更好
空闲内存还给OS 不够积极,RSS容易虚高 支持主动purge归还内存
内存统计 功能弱 自带完善内存统计,可以看哪里内存泄露、哪里占用大
体积&开销 系统自带,开箱即用 需要链接库;有一点点额外内存开销

注意:jemalloc不是万能,单线程小程序,两者差距很小;只有多线程高并发场景优势才明显。

哪些软件在用jemalloc?

Redis、Nginx、RocksDB、LevelDB、很多自研KV数据库、ntyco协程项目、Mysql都经常替换成jemalloc。

为什么KV存储特别爱它:KV就是大量小块malloc/free,成千上万key‑value频繁创建销毁,最容易出现锁竞争+内存碎片。

怎么用上jemalloc(小白不用写代码改逻辑)

不需要改一行业务C代码! 编译时链接,或者用LD_PRELOAD动态劫持替换系统malloc函数。

复制代码
# 运行程序前预加载jemalloc,直接替换malloc/free
LD_PRELOAD=libjemalloc.so ./your_kv_server

这就是你之前看过的 LD_PRELOAD 劫持!jemalloc最常见用法就是这样,原有代码完全不动,直接替换内存分配器。

jemalloc缺点(不是完美神器)

  1. 会有少量元数据开销:它自己要记录内存块信息,会多占一点点内存;
  2. tcache本地缓存的内存不会立刻释放,线程手里会留一部分空闲内存,短时间RSS看着偏高;长时间空闲会purge还给操作系统;
  3. 嵌入式资源极小的设备不适合;主要面向服务器。

容易踩坑点

  1. tcache缓存是线程私有的:线程退出时,它tcache里面残留的内存不会立刻归还,短期RSS降不下来;
  2. purge是有成本的,频繁purge会消耗CPU;jemalloc会有阈值控制,不会没事反复还给OS。

📌一句话总结

jemalloc是高性能内存分配器。靠线程本地缓存tcache + 多独立arena,大幅降低多线程malloc的锁竞争,同时更好控制内存碎片;很多存储、网络服务通过LD_PRELOAD直接替换系统malloc,业务代码一行不改就能提升性能。

和你之前学过的技术关联回顾

  1. fork:创建进程,内存管理交给分配器;
  2. ntyco协程 + io_uring做高性能KV;KV大量小块内存申请释放,搭配jemalloc就是经典组合;
  3. LD_PRELOAD:可以劫持malloc函数,无缝换成jemalloc。

参考链接 :0voice · GitHub

相关推荐
未济3 天前
linux 配置环境变量
linux
傲世仙尊3 天前
目录即文件-Ext文件系统收尾篇
linux·c语言
_艾伦 耶格尔.3 天前
进程间通信
linux
Liuqy-053 天前
Linux IO编程——静态库、动态库
linux
彧azz3 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
-梅3 天前
linux(8) 软硬链接
linux·运维·服务器
AIgorithmGEEK3 天前
[Linux]线程三部曲(上):一个执行流的诞生——从操作系统一路拆到 pthread_create
linux·线程·pid
琥珀色糖3 天前
SimlpeHttp
linux·服务器
qeen873 天前
【Linux】操作系统之进程介绍(二)
linux·笔记·学习·进程
Zenova EdgeOS3 天前
Linux ss 工业边缘网络分析实战
linux·python·边缘计算·工业网关