vmhwm不靠谱,因其仅统计进程自启动以来最高rss值,不含子进程、共享页及复用页,且不可重置、不适合高频采样。

Linux 下用 /proc/[pid]/status 读取进程 RSS 峰值不靠谱
很多人一上来就查 cat /proc/[pid]/status | grep VmHWM,以为 VmHWM(High Water Mark)就是物理内存占用峰值——它确实是,但只统计该进程**自启动以来**的最高 RSS 值,且**不包含子进程、共享内存映射页、或被内核回收后又复用的页**。更关键的是:VmHWM 在进程退出前不会重置,也无法被用户态主动清零或轮询刷新为“当前会话峰值”。如果你在做长期监控或服务健康检查,靠它会漏掉中间抖动。
-
VmHWM单位是 KB,需手动换算;cat读取有延迟,不适合高频采样(>10Hz 时 I/O 开销明显) - 同一进程 fork 出的子进程内存独立计数,
VmHWM不反映父子总和 - 如果进程用了
mmap(MAP_SHARED)或大页(hugetlb),这部分可能未计入 RSS,但实际占物理内存
Windows 上用 GetProcessMemoryInfo 获取 PeakWorkingSetSize
Windows 提供了稳定接口:GetProcessMemoryInfo 返回的 PROCESS_MEMORY_COUNTERS 结构里,PeakWorkingSetSize 字段才是你真正需要的“物理内存占用历史峰值”(单位字节)。它跟踪的是工作集(Working Set)的最高水位,即该进程曾锁定在物理内存中的最大页数。
- 必须链接
psapi.lib,头文件含<psapi.h></psapi.h> - 调用前需确保有
PROCESS_QUERY_INFORMATION权限;服务进程若以 LocalSystem 运行,默认有,但沙箱/容器中可能被限制 - 该值在进程生命周期内单调递增,重启进程才会归零——适合做单次运行任务的资源审计,但不适合长周期服务的滚动峰值(比如每小时最大值)
- 注意:它不含 pagefile 使用量,也不反映硬页错误频率,纯物理内存视角
// 示例:获取当前进程峰值
PROCESS_MEMORY_COUNTERS pmc = {};
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
printf("PeakWorkingSetSize: %zu bytes\n", pmc.PeakWorkingSetSize);
}
跨平台统一方案:用 mallinfo / malloc_info 辅助判断堆峰值(仅限 malloc 管理的内存)
如果你关心的是 C++ new/malloc 分配的堆内存峰值(而非整个进程物理驻留),mallinfo(glibc)或 malloc_info(XML 输出)更轻量、可高频调用。但注意:mallinfo.uss(非共享尺寸)≈ 当前堆用量,而 mallinfo.hblkhd(已分配但未映射的 sbrk 块)能间接反映历史分配压力。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
mallinfo已被标记为 deprecated,新项目建议用malloc_stats()+ 解析 stderr 或直接调用__malloc_stats()(glibc 内部) - 它完全不统计
mmap分配的大块内存(如 std::vector 超过 MMAP_THRESHOLD 后走 mmap),所以峰值会偏低 - Windows 无原生对应,需用
_msize+ 自维护分配器日志,或改用 jemalloc/tcmalloc 并启用 stats 接口
真·系统级物理内存峰值:Linux 用 /sys/fs/cgroup/memory(容器/服务级)
如果你不是监控单个进程,而是想看某个服务(systemd service、Docker 容器)在整个生命周期内的物理内存峰值,/sys/fs/cgroup/memory/memory.max_usage_in_bytes 是唯一可靠来源。它由内核 cgroup v1/v2 统计,精确到页,含所有子进程、线程、匿名映射、tmpfs,且支持实时轮询。
- 路径依赖 cgroup 路径,例如 systemd 服务默认在
/sys/fs/cgroup/memory/system.slice/myapp.service/ - 需 root 或 cgroup read 权限;普通用户可通过
systemctl show myapp --property=MemoryMax查配置,但无法读 usage - 该值在 cgroup 销毁(服务 stop)后仍保留,直到被覆盖或手动重置(写 0 到
memory.usage_in_bytes不生效,只能靠重启 cgroup) - 注意:cgroup v1 和 v2 的路径、字段名略有不同(v2 用
memory.current和memory.peak),务必先cat /proc/cgroups确认版本
真正难的不是读哪个字段,而是搞清你要的“峰值”属于哪一层:进程粒度?服务粒度?还是整机?选错层级,数据就失去意义。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










