如何在运行时跟踪所使用的总内存量?
如何在运行时跟踪所使用的总内存量?
我需要在程序运行时获取我的程序的内存使用情况(VIRT和RES)并显示出来。\n我目前尝试了以下方法:\n使用getrusage(http://linux.die.net/man/2/getrusage)函数\n
int who = RUSAGE_SELF; struct rusage usage; int ret; ret=getrusage(who,&usage); cout<\n但我始终得到的结果都是0。
问题的原因是之前的方法并不能准确地跟踪运行时使用的总内存量。解决方法是通过使用libproc库来获取进程的信息,并使用该信息来获取内存使用量。
首先需要安装libproc库,然后使用下面的代码来获取内存使用量:
// getrusage.c #include#include int main() { struct proc_t usage; look_up_our_self(&usage); printf("usage: %lu\n", usage.vsize); }
编译命令为“gcc -o getrusage getrusage.c -lproc”。
这种方法在Ubuntu下测试通过,需要安装libproc-dev包。使用“usage.vm_data”字段可以获得接近所需的内存使用量。可用的内存统计选项在“/usr/include/proc/readproc.h”中有文档记录。我尝试过的选项似乎都是以字节为单位,而不是页面数。我不认为我的进程使用了4600万个页面。说这种方法在Linux下不起作用的评论似乎是不正确的。
正确的链接器命令是“-lprocps”。
这个方法非常有效,应该被接受为答案!
如何在运行时跟踪内存使用总量?
问题的原因:用户想要在运行时跟踪内存使用的总量。
解决方法:使用下面提供的代码来获取进程的常驻集大小(物理内存使用)。代码包含了不同操作系统的实现。
#include#include size_t getCurrentRSS( ) { struct rusage rusage; getrusage( RUSAGE_SELF, &rusage ); return (size_t)(rusage.ru_maxrss * 1024L); }
在使用上述代码时,用户可以调用`getCurrentRSS()`函数获取当前的常驻集大小。这个函数将返回以字节为单位的物理内存使用量。
用户还可以使用`getPeakRSS()`函数来获取峰值常驻集大小。该函数将返回已使用的最大物理内存量。
用户可以根据需要在代码中添加`#pragma comment(lib, "psapi.lib")`,将其放在`#if defined(_WIN32)`的范围内。这个指令是为了在使用Microsoft编译器的Windows环境下编译代码,以避免出现编译错误。
需要注意的是,如果用户使用的是Windows操作系统但不是Microsoft编译器,那么这个指令会导致编译器失败。
另外,这段代码使用了`getrusage`函数中的`rusage::ru_maxrss`来获取物理内存使用量。但是有用户报告说这个函数在她的系统上不起作用。
更多讨论和相关的函数可以在原网页上找到。原网页还提供了一个获取系统物理内存大小的函数。
如何在运行时跟踪内存总使用量?
在Linux上,我从未找到一个ioctl()的解决方案。对于我们的应用程序,我们编写了一个基于读取/proc/pid文件的通用实用程序例程。这些文件中有一些给出了不同的结果。这是我们最终选择的一个(问题标记为C++,我们使用C++构造处理I/O,但如果需要,它应该很容易适应C I/O例程):
#include#include #include #include #include ////////////////////////////////////////////////////////////////////////////// // // process_mem_usage(double &, double &) - 通过引用获取两个double, // 尝试读取进程虚拟内存大小和常驻内存集大小的系统相关数据,并以KB为单位返回结果。 // // 失败时,返回0.0,0.0 void process_mem_usage(double& vm_usage, double& resident_set) { using std::ios_base; using std::ifstream; using std::string; vm_usage = 0.0; resident_set = 0.0; ifstream stat_stream("/proc/self/stat",ios_base::in); string pid, comm, state, ppid, pgrp, session, tty_nr; string tpgid, flags, minflt, cminflt, majflt, cmajflt; string utime, stime, cutime, cstime, priority, nice; string O, itrealvalue, starttime; unsigned long vsize; long rss; stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt >> utime >> stime >> cutime >> cstime >> priority >> nice >> O >> itrealvalue >> starttime >> vsize >> rss; // 不关心其余部分 stat_stream.close(); long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; vm_usage = vsize / 1024.0; resident_set = rss * page_size_kb; } int main() { using std::cout; using std::endl; double vm, rss; process_mem_usage(vm, rss); cout << "VM: " << vm << "; RSS: " << rss << endl; }
关于不同*nix平台下/proc/self/stat结构的保证,你有什么保证?...我不确定,但如果有的话,那将很好。
好吧,多年来我主要使用Solaris、HP-UX和Linux。/proc/self/stat似乎是Linux特有的。上面的程序的原始版本在Solaris上有#if块,因为它有所不同。
我假设OP只关心Linux,根据问题标记,读取/proc将是你能得到的最好的结果。在Solaris上,您还可以通过kstat获取有关各种信息(尽管它通常会复制您可以通过其他方式获取的信息)。
我只是迟到了10年,但您介意告诉我为什么除以1024.0而不是1024吗?
'river',抱歉,但正如你所说,多年过去了。如果我有任何原因,那已经失去了(我没有通过注释将特殊选择记录下来,我让大家失望了)。我唯一的辩解是,在这种情况下,1024.0可以表示1024而不会失去精度...
关于`为什么是1024.0?` - 这告诉编译器首先将其转换为double,然后进行除法以获得double结果。另一种选择是`vm_usage = vsize / 1024;`,它会首先执行除法(可能会丢失精度),然后转换为double。