hcache是基于pcstat改进的linux缓存分析工具,支持--pid查进程级文件缓存占用和--top全局排序,精准定位pagecache大户。

别急着释放缓存——先搞清是哪个进程把文件塞进 PageCache 的,否则你清完 5 分钟又涨回来。
用 hcache --pid 查指定进程的 PageCache 占用
Linux 自带工具(如 ps、top)看不到进程对 PageCache 的隐式占用,因为这部分内存不计入进程的 RSS 或 USS。真正能定位“谁在缓存哪些文件”的,是 hcache 这类基于 pcstat 原理的增强工具。
安装后直接按 PID 查:
hcache --pid 1234 --bname
输出里每行代表该进程打开过、并被内核缓存过的文件,关键列是 Cached(当前驻留内存的页数)和 Percent(缓存率)。常见高缓存进程包括:
- Nginx/Apache:大量静态资源(JS/CSS/图片)被反复读取后常驻 cache
- Java 应用:JVM 启动时读取的 jar 包、配置文件、日志轮转产生的旧日志文件
- 数据库(PostgreSQL/MySQL):预读或 WAL 日志相关文件可能长期保留在 page cache 中
⚠️ 注意:--pid 只统计该进程当前打开的文件句柄所关联的缓存页,不包含它曾经读过但已关闭的文件——这类“幽灵缓存”需用 --top 全局扫描。
用 hcache --top 找系统级 PageCache 大户
当 free -h 显示 buff/cache 高但 available 仍充足,说明缓存本身不是问题;但如果 available 持续偏低、且 drop_caches 后很快回弹,就得查具体是哪些文件在吃内存。
运行:
hcache --top 10
结果中重点关注 Cached 列(实际占用页数)和 Name 路径。典型高缓存文件包括:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
-
/var/log/*.log:尤其滚动日志未压缩归档时,旧日志文件体积大、访问少,却长期滞留 cache -
/usr/lib/jvm/*/jre/lib/*.jar:Java 类加载器读取后不会主动释放,整包缓存 -
/opt/app/data/*.dat:某些应用自定义数据文件,读取一次就占几 GB cache
? 小技巧:加 --bname 可截断路径显示简名,避免长路径刷屏;加 --json 方便脚本解析。
为什么不用 /proc/PID/fd + ls -l 手动查?
有人试图遍历 /proc/1234/fd/ 下所有符号链接,再用 stat 看文件大小,以为“大文件 = 高缓存”。这是错的:
- 文件大小 ≠ 缓存页数:
ls -l显示的是磁盘大小,而 PageCache 只缓存实际被读过的部分(比如只读了前 1MB,哪怕文件 10GB,也只缓存那 1MB 对应的页) - 硬链接/删除未关闭文件:
/proc/PID/fd/里可能指向已删除但句柄未关的文件((deleted)),stat会失败,但其缓存页依然存在 - 映射文件(mmap):通过
mmap加载的文件不会出现在fd/下,但同样进入 PageCache
所以必须依赖内核暴露的页映射信息,也就是 hcache 底层调用的 mincore() 和 pcstat 逻辑,才能真实反映“哪些页当前在内存里”。
drop_caches 前必须跑 sync,但别滥用
执行 echo 3 > /proc/sys/vm/drop_caches 之前,官方文档明确要求先运行:
sync
原因很实在:PageCache 里可能有“脏页”(修改过但还没写回磁盘的数据),drop_caches 只清理干净页;不 sync 就强清,会导致数据丢失。
但更关键的是使用场景限制:
- 仅适用于调试、压测复位、或确认某服务是否因缓存污染导致性能下降
- 生产环境频繁执行会引发 IO 尖峰(内核要批量回写+重建 cache),反而拖慢响应
- 如果
available正常,drop_caches后buff/cache立刻回升是健康表现,不是 bug
真正该干预的,是那些长期霸占 cache 却几乎不被再次访问的大文件——找到它们,删掉、归档、或用 fadvise 提示内核“别缓存我”,比定期清 cache 更治本。










