对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

相关推荐
发光的沙子1 小时前
嵌入式系统架构师----Ubuntu如何安装不在列表内的软件?
linux·运维·ubuntu
C+ 安口木1 小时前
Alibaba Cloud Linux 3 服务器环境搭建实战记录
linux·运维·服务器
come112343 小时前
剪映零基础教程
java·linux·运维
飘忽不定的bug3 小时前
ubuntu20.04交叉编译QT5.15.12(RK3562+ubuntu20.04)
linux·qt·ubuntu
库玛西4 小时前
深入浅出Linux select网络模型:从底层位图原理到C++面向对象高级封装
linux·服务器·网络·c++·ubuntu
Tingjct4 小时前
线程详细讲解---聚焦linux
linux·服务器·jvm
ComputerInBook4 小时前
linux包管理工具——yum(YellowdogUpdaterModified)
linux·运维·服务器·yum·dnf
霸道流氓气质4 小时前
通义千问 Chat 模型高级用法:Function Calling / Structured Output / 多轮对话
linux·运维·windows
实心儿儿4 小时前
Linux —— epoll(1)
linux·网络