linux 用 /proc/self/status 的 vmhwm 字段获取物理内存峰值(kb),macos 用 task_info() 的 phys_footprint 采样比较得峰值,windows 用 getprocessmemoryinfo() 的 peakworkingsetsize 获取峰值(字节)。

Linux 下用 /proc/self/status 读取 VmHWM
Linux 内核会在 /proc/self/status 中记录当前进程的内存使用快照,其中 VmHWM(Virtual memory High Water Mark)字段直接表示自启动以来的物理内存峰值(单位 KB)。这是最轻量、最可靠的方式,无需链接额外库或 root 权限。
实操建议:
- 用
std::ifstream打开/proc/self/status,逐行读取直到匹配"VmHWM:"开头的行 - 注意字段后有制表符或空格分隔,用
std::istringstream提取第一个整数即可,别依赖固定列偏移 - 该值是 RSS 峰值(实际占用的物理内存),不含 swap,也不含 mmap 的匿名大页预留(除非已触达并提交)
- 不是实时更新——内核只在内存管理关键路径(如缺页、释放页框)更新此值,但对“峰值”语义完全足够
macOS 下用 task_info() 获取 phys_footprint
macOS 没有 /proc,需调用 Mach API。核心是 task_info() + TASK_VM_INFO64,返回结构体中的 phys_footprint 字段,单位字节,代表当前物理内存占用;但它不直接提供“历史峰值”。要拿到峰值,得自己采样+比较。
实操建议:
- 包含
<mach></mach>和<mach></mach>,用mach_task_self()获取当前 task port - 每次调用
task_info()前检查返回值是否为KERN_SUCCESS,失败时不要假设数据有效 - 把
phys_footprint存进全局变量或原子变量,在关键路径(如大对象分配后、模块初始化完成时)手动更新最大值 - 避免高频轮询——
task_info()是系统调用,开销比读/proc高得多;每秒几次足矣
Windows 下用 GetProcessMemoryInfo() 的 PeakWorkingSetSize
Windows 提供 PROCESS_MEMORY_COUNTERS_EX 结构,其中 PeakWorkingSetSize 字段即工作集峰值(单位字节),含义接近 Linux 的 VmHWM:进程曾占用的最大物理内存大小。
实操建议:
- 链接
psapi.lib,调用前确保结构体cb成员设为sizeof(PROCESS_MEMORY_COUNTERS_EX),否则 API 返回失败 -
GetProcessMemoryInfo()只读当前进程时,句柄用GetCurrentProcess()即可,无需权限提升 - 该值不会自动重置,从进程创建起累计;若需分阶段观测(如某函数执行期间),需在阶段开始前手动记录初始值再做减法
- 注意:它不包括 standby list 中的页面(Windows 内存管理特有机制),但对绝大多数应用级峰值评估已足够准确
跨平台封装要注意的三个事实
没有标准 C++ 接口能跨平台返回内存峰值,任何“抽象一层”的尝试都会掩盖差异。硬要统一封装,必须接受以下事实:
- Linux 的
VmHWM是内核维护的精确值;macOS 和 Windows 的对应字段都是用户态采样/估算,存在微小延迟或舍入 - 所有平台的“峰值”都不区分 malloc/new 分配与 mmap 映射——只要进了物理内存,就算
- 多线程下,峰值是整个进程的,无法按线程隔离;若想追踪某线程局部峰值,只能靠该线程主动打点+比较
真正容易被忽略的是:峰值统计本身不消耗内存,但频繁读取(尤其 macOS 的 task_info())会成为性能瓶颈。生产环境建议只在初始化、关键模块加载后、以及程序退出前各查一次。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











