Linux系统无直接接口获取物理内存峰值,进程级峰值需读取/proc/[pid]/status的VmHWM字段;Windows对应PeakWorkingSetSize;系统级峰值须自行采样聚合,mallinfo等堆信息接口不可靠。

Linux 下用 /proc/meminfo 和 /proc/[pid]/status 查物理内存峰值
Linux 没有直接暴露“系统级物理内存占用峰值”的单一接口,/proc/meminfo 只提供当前快照(如 MemTotal、MemAvailable),不记录历史峰值。真正的峰值监控必须靠持续采样 + 自行维护最大值。
如果你关心的是**某个进程的物理内存使用峰值**,那关键字段是 /proc/[pid]/status 中的 VmHWM(High Water Mark,单位 KB)——它表示该进程自启动以来 RSS 达到过的最高值,内核自动维护,读取即得,无需轮询。
- 获取当前进程峰值:
cat /proc/self/status | grep VmHWM
- 在 C++ 中读取:
std::ifstream("/proc/" + std::to_string(getpid()) + "/status"),逐行解析含VmHWM:的行,提取数字即可 - 注意:该值只在进程生命周期内有效,重启后归零;子进程不继承父进程的
VmHWM
Windows 上调用 GetProcessMemoryInfo 获取工作集峰值
Windows 没有等价于 Linux VmHWM 的“自动累计峰值”字段。但 PROCESS_MEMORY_COUNTERS_EX 结构体里的 PeakWorkingSetSize 字段,是内核为每个进程维护的、自创建以来工作集(Working Set)的最大字节数,可直接读取,无需自己累加。
- 需链接
psapi.lib,头文件包含 - 调用前确保启用
SE_DEBUG_NAME权限(否则可能返回 0 或失败) - 示例关键代码:
PROCESS_MEMORY_COUNTERS_EX pmc = {0}; pmc.cb = sizeof(pmc); if (GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc))) { size_t peak_kb = pmc.PeakWorkingSetSize / 1024; } - 注意:
PeakWorkingSetSize统计的是工作集(驻留内存),不是 RSS 全集;若进程被换出或受内存压缩影响,该值可能低于实际物理页峰值
C++ 跨平台采样监控要避开的三个坑
想自己实现系统级内存峰值监控(比如每秒读一次总内存使用并记最大值),不能只依赖单次读数,更不能误以为 VmHWM 或 PeakWorkingSetSize 是系统级指标——它们全是进程粒度的。
- Linux 系统总 RSS 峰值无法直接获取:只能用
ps -eo rss= | awk '{sum+=$1} END{print sum}'类似方式聚合所有进程 RSS,再自行维护全局最大值;但开销大、竞态明显(进程启停瞬间漏统计) - Windows 无等效聚合 API:不能用
GlobalMemoryStatusEx,它只返回当前可用/已用,不存历史;必须遍历进程(CreateToolhelp32Snapshot+Process32First/Next),对每个调用GetProcessMemoryInfo,再求和取峰 —— 性能敏感场景慎用 - 采样频率陷阱:间隔太短(如 100ms)会显著拖慢系统,尤其 Windows 遍历进程本身是重量级操作;建议 ≥1s,且首次启动时先 sleep 再采样,避免把初始化抖动计入峰值
为什么不用 mallinfo 或 malloc_stats 查物理内存峰值
这两个接口只反映堆管理器(glibc malloc)的内部状态,比如 mallinfo.uss 或分配区总量,完全不等价于物理内存占用。它们不统计 mmap 分配的大块内存、不包含共享库、不计入内核为进程分配的页表/缓冲区等 —— 实际物理 RSS 往往比 mallinfo 报告的高 2–5 倍。
-
mallinfo已被标记为废弃(POSIX.1-2008),glibc 2.33+ 默认禁用,编译会警告 -
malloc_stats()输出到 stderr,不可靠解析,且无峰值字段,只有当前快照 - 真实场景中,一个用了
mmap(MAP_ANONYMOUS)或加载了大动态库的程序,mallinfo完全无法体现其物理内存压力
真正可靠的物理内存峰值,要么依赖内核自动维护的进程级字段(VmHWM / PeakWorkingSetSize),要么自己做带防抖的跨进程聚合采样。别指望一个函数调用就拿到“系统历史最高物理占用”——这个值不存在于任何标准接口里,得你来定义、采集、容错、落地存储。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











