bigywater.tech
Elasticsearch · 148

Off-Heap 内存与 mmap

本机真实用ps查ES进程RSS是1421MB,比配置的1024MB堆上限还大,证明存在JVM堆之外的off-heap内存;用vmmap查虚拟内存分布发现VSZ真实高达469GB,其中Guard区域虚拟385GB但resident为0,证明虚拟地址空间预留不等于真实物理内存消耗;细看mapped file区域发现178.4MB映射只有16.5MB真实resident,并列出具体映射文件正是本机es-lab数据目录下真实的Lucene段文件,完整还原了mmap机制如何让ES在有限物理内存下随时准备好访问远超内存容量的索引数据。

ps查进程RSS
真实1421MB,比1024MB堆上限还大
vmmap查虚拟内存
VSZ真实469GB,Guard区域385GB却0K resident
mapped file区域细看
178.4MB映射只有16.5MB真实resident

做的事:本机真实用ps查ES进程的RSS(实际占用的物理内存),对比配置的JVM堆上限

代码ps -o pid,rss,vsz -p <ES真实的进程PID> GET /_nodes/stats/jvm # 真实对照配置的heap_max

验证:RSS真实是1421MB,比配置的1024MB堆上限还大——这部分差额真实就是JVM堆以外的off-heap内存

实测 · 本机 Elasticsearch 8.15.0 执行输出
ps真实查到: RSS=1455360KB(≈1421MB)  VSZ=491642048KB(≈469.6GB)
heap_max_in_bytes: 1024MB

真实RSS(1421MB) > heap_max(1024MB),差额约397MB

这个真实对比直接证明了ES进程占用的物理内存真实不等于配置给它的JVM堆大小——除了堆内存之外,JVM自身的元空间、线程栈、直接内存缓冲区,以及Lucene用mmap映射进来的那些索引文件,真实都算在进程的RSS里,但真实都不受-Xmx这个参数的限制。

真实用vmmap命令查这个进程完整的虚拟内存分布,看VSZ为什么会真实这么离谱地大

代码vmmap -summary <ES真实的进程PID>

验证:VSZ真实高达469GB,其中有一块Guard区域虚拟大小385GB但resident是0——真实的物理内存占用其实只有1.4GB

实测 · 本机执行输出
Physical footprint:         1.4G   ← 真实的物理内存占用
Guard区域: VIRTUAL=385.0G  RESIDENT=0K   ← 真实预留的巨大虚拟地址空间,完全没有真实物理内存支撑
这组真实数据完美展示了虚拟内存和物理内存是两件完全不同的事:操作系统真实允许一个进程预留出远超实际物理内存容量的虚拟地址空间(本次实测真实预留了接近400GB),这些预留的地址真实只是"占了个位置",直到真正被访问到的那一刻才会真实消耗物理内存——这正是mmap这类机制之所以能够"假装"把远超物理内存大小的文件映射进内存却不会立刻撑爆机器的真实原理。

真实再往细看mapped file这一类区域的具体数字,以及这些映射真实对应的是哪些文件

代码vmmap <ES真实的进程PID> | grep "es-lab/data"

验证:mapped file这一类区域真实映射了178.4MB,但真实只有16.5MB是resident的;具体文件路径真实就是本机es-lab数据目录下那些真实的Lucene segment文件

实测 · 本机执行输出
mapped file: VIRTUAL=178.4M  RESIDENT=16.5M(只有约9%真实驻留在物理内存里)

真实列出的具体映射文件(节选):
→ .../es-lab/data/indices/actIPdfcSUCv_IOX-4k6IQ/0/index/_0.cfs
→ .../es-lab/data/indices/D7oaV8ILSAeiawx3WSbetg/0/index/_1.cfs
(这些都是真实本系列从头用到现在的es-lab索引对应的Lucene段文件)

这组真实数据把off-heap内存和mmap的关系讲得非常具体:Elasticsearch底层的Lucene真实不会把索引文件整个读进JVM堆里,而是真实用mmap系统调用,把磁盘上这些段文件(.cfs这类压缩复合文件)直接映射进进程的虚拟地址空间,只有真实被查询访问到的那些页面才会被操作系统真实加载进物理内存(本次实测178.4MB的映射里,真实只有16.5MB被真正访问过变成了resident状态)。这意味着索引数据再大,只要真实不是所有数据都被频繁访问,mmap机制真实能让ES在有限的物理内存下,依然能够"随时准备好"访问远超物理内存容量的索引数据。

分步演示:从RSS超出堆上限的真实差额,到vmmap揭示的巨大虚拟地址空间,再到具体Lucene段文件的真实mmap映射

每一步都是本文上面在本机真实的Elasticsearch 8.15.0进程上跑出来的原始结果。

off-heap内存真实存在于JVM堆之外,mmap真实能映射远超物理内存的索引文件却只在真正访问时才消耗真实内存
这一步新验证的off-heap内存场景

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 ps 与 vmmap 系统工具查看进程内存分布
    京ICP备2026067502号-1京公网安备11010502063487号