linux用/proc/self/status读vmrss(kb)除以memtotal得物理内存占用百分比;windows用getprocessmemoryinfo获取workingsetsize(字节)除以ulltotalphys计算,二者均不可用mallinfo等替代。

Linux 下用 /proc/self/status 读取 RSS 并换算为百分比
Linux 系统里没有“实时物理内存占用百分比”的标准 API,得自己算:先读 /proc/self/status 中的 RssAnon、RssFile、RssShmem(或更常用但略粗略的 VmRSS),加总得到当前 RSS(单位 KB),再除以系统总内存(来自 /proc/meminfo 的 MemTotal:)即可得百分比。
注意:VmRSS 是最常用字段,它等于 RssAnon + RssFile + RssShmem,代表进程实际占用的物理内存页,不含 swap,也不含共享库未映射部分。别用 VmSize(虚拟地址空间大小),那和物理内存无关。
示例片段(C++17):
#include <fstream>
#include <string>
#include <regex><p>size_t get_rss_kb() {
std::ifstream f("/proc/self/status");
std::string line;
while (std::getline(f, line)) {
if (std::regex_match(line, std::regex(R"(^VmRSS:\s+(\d+)\s+kB)"))) {
return std::stoul(line.substr(line.find_first_of("0123456789")));
}
}
return 0;
}</p>
<p>size_t get_total_mem_kb() {
std::ifstream f("/proc/meminfo");
std::string line;
while (std::getline(f, line)) {
if (line.rfind("MemTotal:", 0) == 0) {
return std::stoul(line.substr(9));
}
}
return 0;
}</p></regex></string></fstream>
计算百分比时建议用 double(get_rss_kb()) / get_total_mem_kb() * 100.0,避免整数截断。
Windows 下用 GetProcessMemoryInfo 获取 WorkingSetSize
Windows 没有直接等价于 Linux RSS 的概念,最接近的是 PROCESS_MEMORY_COUNTERS_EX::WorkingSetSize —— 它表示当前进程在物理内存中驻留的字节数(含私有页和共享页,但不含 pagefile-backed 部分)。这个值就是你要的“物理内存占用”基础。
调用前必须链接 psapi.lib,且需启用 SE_DEBUG_NAME 权限才能准确获取其他进程数据(本进程无需);对本进程,直接调用即可。
关键点:
-
WorkingSetSize单位是字节,要除以 1024 再除以系统总内存(用GlobalMemoryStatusEx获取ullTotalPhys)才能得百分比 - 不要用
PagefileUsage或PrivateUsage,前者含 swap,后者不含共享内存,都会低估/高估真实物理占用 - 该值每秒变动可能达几 MB,建议采样间隔 ≥100ms,否则抖动太大
跨平台采样与趋势绘制的实际约束
所谓“变动趋势”,本质是时间序列数据采集问题,不是 C++ 语言本身能解决的。你得自己做三件事:定时读取、缓存最近 N 个点、输出或绘图。没有现成“趋势 API”。
常见陷阱:
- 频繁读
/proc/self/status(如每 10ms)会显著增加 syscalls 开销,尤其在容器环境或高负载机器上,反而影响被测程序自身表现 - Windows 上
GetProcessMemoryInfo调用开销比 Linux 读 proc 文件大,连续高频调用易触发内核锁竞争 - 内存值本身存在“抖动”:malloc 后未立即使用、page fault 延迟分配、glibc 的 malloc arena 合并行为,都会导致 RSS 短时非单调变化,不能简单画折线就当“趋势”
- 若程序用了
mmap(MAP_SHARED)或大页(huge pages),VmRSS可能不完全反映真实物理占用(取决于是否真正 touch 过)
为什么不能依赖 mallinfo 或 malloc_stats
mallinfo(已废弃)和 malloc_stats 只反映 glibc malloc 堆管理器的内部状态,比如 uordblks 是已分配但未释放的堆字节数,但它不包含 mmap 分配的内存(如大块内存或 std::vector 超过阈值后)、不包含 stack、不包含 shared library 代码段、也不含 kernel data structures(如 socket buffer)。结果通常比 VmRSS 小 30%~70%,完全不可用于物理内存百分比计算。
如果你看到某些老教程用 mallinfo 算“内存占用”,那是错的——它只适合 debug malloc 行为,不是系统级物理内存指标。
真要监控趋势,就得接受:Linux 用 /proc/self/status,Windows 用 GetProcessMemoryInfo,其余全是围绕这两者的工程封装。中间任何抽象层(比如第三方库封装)都可能隐藏采样时机、单位混淆或字段误选的问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











