windows下用globalmemorystatusex获取可用物理内存百分比,需用ullavailphys和ulltotalphys计算,注意设置dwlength并避免整数除法;linux下读取/proc/meminfo的memavailable字段(内核3.14+)。

Windows下用GlobalMemoryStatusEx获取可用物理内存百分比
Windows没有直接提供“内存使用率随时间变化”的API,必须自己采样+计算。关键函数是GlobalMemoryStatusEx,它返回MEMORYSTATUSEX结构体,其中ullAvailPhys(可用物理内存字节数)和ullTotalPhys(总物理内存字节数)才是计算真实百分比的依据。别用dwAvailPhys——那是32位字段,超过4GB会溢出。
-
ullAvailPhys / ullTotalPhys * 100.0才是当前可用内存百分比(注意用double除法,避免整数截断) - 调用前必须设置
memStat.dwLength = sizeof(MEMORYSTATUSEX),否则返回失败 - 该函数开销极低,可每500ms调用一次,不影响主线程;但别塞进高频渲染循环(如60fps帧回调里)
Linux下读取/proc/meminfo解析MemAvailable字段
Linux内核3.14+才稳定支持MemAvailable,它比MemFree更准确反映“真正可立即分配的内存”,已扣除了不可回收的缓存、页表开销等。旧内核(MemFree + Buffers + Cached估算,但误差可能达10%~20%。
- 逐行读
/proc/meminfo,匹配以MemAvailable:开头的行,提取后第一个数字(单位KB) -
MemTotal:字段给出总内存(KB),二者相除即得可用百分比 - 注意:
MemAvailable可能为0(如某些嵌入式发行版或内核配置禁用),此时应fallback到MemFree并记录warn日志
跨平台采样器设计要点:避免std::chrono精度陷阱
用std::this_thread::sleep_for控制采样间隔时,实际休眠时间常比设定值长(尤其在负载高或系统timer分辨率低时)。连续10次500ms采样,可能累积偏差2~3秒,导致走势图时间轴拉伸。
- 改用“固定起始时间 + 累计偏移”方式:记录
start_time = steady_clock::now(),每次循环计算next_sample = start_time + n * interval,再sleep_until(next_sample) - 每次采样后立刻更新
last_sample_time,用于后续插值或丢弃异常延迟点 - 若某次采样耗时超过interval的1.5倍(如设500ms但卡了800ms),跳过本次数据点,防止走势图出现尖刺
绘制动态图表时内存数据不是实时刷新的根源
很多开发者发现曲线“滞后几秒”或“卡顿”,其实不是绘图慢,而是采样线程和UI线程间共享数据的方式不对。用std::vector<double></double>存历史数据并加锁拷贝,会导致UI线程频繁阻塞。
- 改用双缓冲环形队列:
std::array<double></double>+ 两个原子索引(head写,tail读),写端覆盖旧数据,读端只读已提交段 - UI线程每帧只取
tail到head之间最多200个点,避免一次性拷贝全部历史 - 别在采样线程里做任何格式转换(如转字符串、JSON序列化),这些操作应由UI线程按需处理
真实场景中,MemAvailable在Linux上可能因内核kswapd活动而1秒内波动5%,Windows的ullAvailPhys受SuperFetch影响也有类似抖动。走势图平滑不是靠算法滤波,而是靠合理采样周期(建议800ms~1.2s)和剔除离群点——这点容易被忽略,但直接影响曲线可信度。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











