C++使用getrusage测内存时如何重置ru_maxrss峰值统计
算法内存基准测试问题记录与实现方案
背景
在个人数值物理项目开发中,需要对比同一问题下不同算法实现的内存占用表现。前期调研得知,引入<sys/resource.h>头文件后可调用getrusage()接口,通过返回结构体的ru_maxrss字段获取进程最大内存使用量,该接口的已知使用限制不会影响本次测试需求。
初始基准测试逻辑为遍历不同的参数N取值,分别统计各算法的运行耗时与内存占用,代码结构如下:
int minN = 6; int maxN = 16; std::chrono::steady_clock::time_point start; std::chrono::steady_clock::time_point finish; std::cout << "Naive:" << std::endl; for (int N = minN; N <= maxN; N+=2) { struct rusage usage{}; start = std::chrono::steady_clock::now(); //do work... finish = std::chrono::steady_clock::now(); int ret = getrusage(RUSAGE_SELF, &usage); long time_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count(); long max_ram_byte = usage.ru_maxrss; std::cout << "N = " << N << ", time = " << time_ns/1e9 << " s, ram = " << max_ram_byte << " KB" << std::endl; }
测试遇到的问题
测试时发现核心缺陷:ru_maxrss统计的是进程从启动到调用时刻全生命周期的峰值内存占用,大内存对象离开作用域释放内存后,该统计值不会回落。一旦程序运行到内存占用较高的测试用例、触达全局内存峰值后,后续所有测试用例读取到的ru_maxrss都会固定为该历史峰值,内存统计结果完全失效。
典型失效测试输出如下:
Naive: N = 6, time = 0.022541 s, ram = 8028 KB N = 8, time = 0.0234674 s, ram = 65360 KB N = 10, time = 0.373676 s, ram = 135284 KB N = 12, time = 21.7536 s, ram = 631792 KB Magnetization: N = 6, time = 0.000166585 s, ram = 631792 KB N = 8, time = 0.00158378 s, ram = 631792 KB N = 10, time = 0.022255 s, ram = 631792 KB N = 12, time = 0.405172 s, ram = 631792 KB Momentum: N = 6, time = 0.000175482 s, ram = 631792 KB N = 8, time = 0.000766058 s, ram = 631792 KB N = 10, time = 0.00658272 s, ram = 631792 KB N = 12, time = 0.0728279 s, ram = 631792 KB Parity: N = 8, time = 0.000986243 s, ram = 631792 KB N = 12, time = 0.0528302 s, ram = 631792 KB Spin Inversion: N = 8, time = 0.00111167 s, ram = 631792 KB N = 12, time = 0.050363 s, ram = 631792 KB
初始疑问
明确该特性是getrusage()的设计逻辑后,提出三个问题:
- 是否存在方法可以重置
ru_maxrss的峰值统计值? - 若无法重置,是否有无需依赖专用基准测试库、可在程序内部直接调用的简易内存占用测量方案?
ru_maxrss字段的返回值单位是字节(B)还是千字节(KB)?在N=8测试场景中,存储了包含65536个double类型元素的矩阵作为内存占用主体,预期占用约65536字节;按照接口文档说明返回值单位为KB,但测试得到的65360数值与预期字节数意外接近,需要确认该字段的单位规则,以及数值接近是否仅为巧合。
最终实现方案
目前已通过解析/proc/self/stat文件实现了符合需求的内存测量,可供后续开发者参考:
注意:
stat文件的第24项rss字段单位为内存页,将其值乘以4096即可得到近似的内存占用字节数
实现代码如下:
std::cout << "Naive:" << std::endl; for (int N = minN; N <= maxN; N+=2) { start = std::chrono::steady_clock::now(); // do work... finish = std::chrono::steady_clock::now(); std::ifstream statFile("/proc/self/stat"); std::string statLine; std::getline(statFile, statLine); std::istringstream iss(statLine); std::string entry; long long memUsage; for (int i = 1; i <= 24; i++) { std::getline(iss, entry, ' '); if (i == 24) { memUsage = stoi(entry); } } long time_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count(); std::cout << "N = " << N << ", time = " << time_ns/1e9 << " s, ram = " << 4096*memUsage/1e9 << " GB" << std::endl; }
内容的提问来源于stack exchange,提问作者Max Maschke
相关产品推荐
相关产品推荐

