windows 用 getperformanceinfo 获取 committotal/commitlimit 比值得到页面文件虚拟内存占用率;linux 读 /proc/meminfo 中 committed_as/commitlimit;macos 无等效指标,不可强行统一。

Windows 上用 GetPerformanceInfo 获取页面交换文件(Pagefile)使用率
Windows 没有直接返回“页面交换文件占用率”的单一 API,但 GetPerformanceInfo 能拿到当前已提交(committed)内存总量和系统承诺限制(commit limit),二者相除就是页面文件实际承担的负载比例——这正是用户真正想监控的指标。
注意:这个值 ≠ “pagefile.sys 文件磁盘占用率”,而是“所有页面文件合计能提供的虚拟内存中,已被系统承诺使用的百分比”,它直接影响是否触发 OUTOFMEMORY 或进程提交失败。
-
GetPerformanceInfo需要链接Psapi.lib,头文件为<psapi.h></psapi.h> - 调用前必须先用
sizeof(PERFORMANCE_INFORMATION)初始化结构体,否则返回失败(GetLastError()为ERROR_INVALID_PARAMETER) - 返回的
CommitTotal和CommitLimit单位是页面数(通常 4KB),不是字节,别直接当 byte 用 - 若
CommitLimit == 0(极少见,多见于某些容器或精简系统),应视为不可信数据,跳过计算
PERFORMANCE_INFORMATION pi = {};
pi.cb = sizeof(pi);
if (GetPerformanceInfo(&pi, sizeof(pi))) {
if (pi.CommitLimit > 0) {
double rate = static_cast<double>(pi.CommitTotal) / pi.CommitLimit;
// 例如:0.72 表示 72%
}
}</double>
Linux 上读取 /proc/meminfo 中的 Committed_AS 和 CommitLimit
Linux 内核从 2.6.29+ 开始在 /proc/meminfo 暴露 Committed_AS(已估算的总提交量)和 CommitLimit(理论最大可提交量),二者比值语义与 Windows 的 CommitTotal/CommitLimit 一致,是跨平台监控页面交换压力最可靠的指标。
注意:SwapTotal 和 SwapFree 只反映 swap 分区/文件的磁盘空间使用,不等于虚拟内存压力;而 Committed_AS 才体现内核对“未来可能需要换出的内存页”的预估总量。
- 需以文本方式打开并逐行解析
/proc/meminfo,不能依赖固定行号 -
Committed_AS值后缀通常是kB,有些内核版本可能为B或无单位,建议用sscanf(line.c_str(), "Committed_AS: %lld %*s", &val)容错提取 -
CommitLimit在启用 overcommit(/proc/sys/vm/overcommit_memory == 1)时可能为 0,此时该比率无意义,应降级为检查SwapUsed = SwapTotal - SwapFree
macOS 没有等效的页面交换文件使用率指标
macOS 不区分“页面文件”和物理内存管理,其虚拟内存子系统统一使用压缩内存 + anonymous memory + swap files(位于 /private/var/vm/),且不对外暴露类似 CommitLimit 的硬性上限。内核甚至允许 vm_compressor_mode 动态关闭压缩,导致内存压力信号严重滞后。
所以 macOS 上无法获取有意义的“页面交换文件占用率”。唯一接近的替代方案是:
- 用
host_statistics64(host_port, HOST_VM_INFO64, ...)拿到vm_stat_t中的pages_pageable_internal等字段,但它们不包含 swap 文件用量 - 轮询
/private/var/vm/下swapfile*的stat()大小,再除以sysctlbyname("vm.swapusage", ...)返回的xlsw_usage_t::total—— 但这只是磁盘文件大小占比,和内存压力无关,且系统可能根本不创建 swapfile(全靠压缩)
实践中,macOS 应改用 host_processor_info() 配合 mach_host_self() 监控 load_average 和 cpu_ticks,或监听 NSWorkspaceDidWakeNotification 后查 activityMonitor 的 memoryPressure 属性(10.15+)。
跨平台封装时最容易被忽略的点
不同系统对“页面交换压力”的定义根本不同:Windows/Linux 关注的是虚拟内存提交上限是否逼近,而 macOS 根本没有这个概念。强行统一接口会掩盖关键差异。
- 不要把 Windows 的
CommitTotal/CommitLimit和 Linux 的SwapUsed/SwapTotal混为一谈——前者可能超 100%(触发 OOM killer),后者永远 ≤100% - Linux 的
CommitLimit受/proc/sys/vm/overcommit_ratio和overcommit_memory影响,同一台机器重启后值可能变化,不能硬编码阈值 - 所有读取操作都应在非主线程完成,尤其是
/proc/meminfo在高 I/O 负载下可能阻塞数百毫秒 - Windows 下若进程无
SE_PROF_SINGLE_PROCESS权限(如普通用户启动),GetPerformanceInfo仍可成功,但CommitTotal可能偏低(只含本进程),需用OpenProcessToken+AdjustTokenPrivileges提权才能获取全局值
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











