Linux 如何使用 C++ 在运行时获取内存使用情况?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/669438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get memory usage at runtime using C++?
提问by
I need to get the mem usage VIRT and RES at run time of my program and display them.
我需要在程序运行时获取内存使用情况 VIRT 和 RES 并显示它们。
What i tried so far:
到目前为止我尝试过的:
getrusage (http://linux.die.net/man/2/getrusage)
getrusage ( http://linux.die.net/man/2/getrusage)
int who = RUSAGE_SELF;
struct rusage usage;
int ret;
ret=getrusage(who,&usage);
cout<<usage.ru_maxrss;
but i always get 0.
但我总是得到0。
回答by Paul de Vrieze
Old:
老的:
maxrss states the maximum available memory for the process. 0 means that no limit is put upon the process. What you probably want is unshared data usage
ru_idrss
.
maxrss 表示进程的最大可用内存。0 表示对进程没有限制。您可能想要的是非共享数据使用
ru_idrss
。
New: It seems that the above does not actually work, as the kernel does not fill most of the values. What does work is to get the information from proc. Instead of parsing it oneself though, it is easier to use libproc (part of procps) as follows:
新:似乎上述实际上不起作用,因为内核没有填充大部分值。有效的是从 proc 获取信息。虽然不是自己解析它,而是使用 libproc(procps 的一部分)更容易,如下所示:
// getrusage.c
#include <stdio.h>
#include <proc/readproc.h>
int main() {
struct proc_t usage;
look_up_our_self(&usage);
printf("usage: %lu\n", usage.vsize);
}
Compile with "gcc -o getrusage getrusage.c -lproc
"
用“ gcc -o getrusage getrusage.c -lproc
”编译
回答by bayda
in additional to your way
you could call system ps command and get memory usage from it output.
or read info from /proc/pid ( see PIOCPSINFO struct )
除了您的方式之外,您
还可以调用 system ps 命令并从它的输出中获取内存使用情况。
或从 /proc/pid 读取信息(请参阅 PIOCPSINFO 结构)
回答by David Cournapeau
On linux, if you can afford the run time cost (for debugging), you can use valgrind with the massif tool:
在 linux 上,如果您负担得起运行时间成本(用于调试),您可以将 valgrind 与 massif 工具一起使用:
http://valgrind.org/docs/manual/ms-manual.html
http://valgrind.org/docs/manual/ms-manual.html
It is heavy weight, but very useful.
它很重,但非常有用。
回答by Don Wakefield
On Linux, I've never found an ioctl()solution. For our applications, we coded a general utility routine based on reading files in /proc/pid. There are a number of these files which give differing results. Here's the one we settled on (the question was tagged C++, and we handled I/O using C++ constructs, but it should be easily adaptable to C i/o routines if you need to):
在 Linux 上,我从未找到ioctl()解决方案。对于我们的应用程序,我们编写了一个基于读取/proc/pid文件的通用实用程序。有许多这些文件会给出不同的结果。这是我们解决的问题(问题被标记为 C++,我们使用 C++ 构造处理 I/O,但如果需要,它应该很容易适应 C i/o 例程):
#include <unistd.h>
#include <ios>
#include <iostream>
#include <fstream>
#include <string>
//////////////////////////////////////////////////////////////////////////////
//
// process_mem_usage(double &, double &) - takes two doubles by reference,
// attempts to read the system-dependent data for a process' virtual memory
// size and resident set size, and return the results in KB.
//
// On failure, returns 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;
// 'file' stat seems to give the most reliable results
//
ifstream stat_stream("/proc/self/stat",ios_base::in);
// dummy vars for leading entries in stat that we don't care about
//
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;
// the two fields we want
//
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; // don't care about the rest
stat_stream.close();
long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
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;
}
回答by Don Wakefield
I am using other way to do that and it sounds realistic. What I do is i got the PID of the process by getpid() function and then I use /proc/pid/stat file. I believe the 23rd column of the stat file is the vmsize (look at the Don post). You may read the vmsize from the file wherever you need in the code. In case you wonder how much a snippet of a code may use memory, you may read that file once before that snippet and once after and you can subtract them from each other.
我正在使用其他方式来做到这一点,这听起来很现实。我所做的是通过 getpid() 函数获取进程的 PID,然后使用 /proc/pid/stat 文件。我相信 stat 文件的第 23 列是 vmsize(查看 Don 帖子)。您可以在代码中需要的任何位置从文件中读取 vmsize。如果您想知道代码片段可能使用多少内存,您可以在该代码片段之前和之后读取该文件一次,并且可以将它们相互减去。
回答by jmanning2k
The existing answers are better for how to get the correct value, but I can at least explain why getrusage isn't working for you.
现有的答案更适合如何获得正确的值,但我至少可以解释为什么 getrusage 对您不起作用。
man 2 getrusage:
人 2 getrusage:
The above struct [rusage] was taken from BSD 4.3 Reno. Not all fields are meaningful under Linux. Right now (Linux 2.4, 2.6) only the fields ru_utime, ru_stime, ru_minflt, ru_majflt, and ru_nswap are maintained.
上面的结构 [rusage] 取自 BSD 4.3 Reno。并非所有字段在 Linux 下都有意义。现在(Linux 2.4、2.6)只维护了 ru_utime、ru_stime、ru_minflt、ru_majflt 和 ru_nswap 字段。
回答by Qsiris
A more elegant way for Don Wakefield method:
Don Wakefield 方法的一种更优雅的方法:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
int tSize = 0, resident = 0, share = 0;
ifstream buffer("/proc/self/statm");
buffer >> tSize >> resident >> share;
buffer.close();
long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
double rss = resident * page_size_kb;
cout << "RSS - " << rss << " kB\n";
double shared_mem = share * page_size_kb;
cout << "Shared Memory - " << shared_mem << " kB\n";
cout << "Private Memory - " << rss - shared_mem << "kB\n";
return 0;
}
回答by pepper_chico
David Robert Nadeauhas put a good self contained multi-platform C function to get the process resident set size (physical memory use)in his website:
David Robert Nadeau在他的网站上放置了一个很好的自包含多平台 C 函数来获取进程驻留集大小(物理内存使用):
/*
* Author: David Robert Nadeau
* Site: http://NadeauSoftware.com/
* License: Creative Commons Attribution 3.0 Unported License
* http://creativecommons.org/licenses/by/3.0/deed.en_US
*/
#if defined(_WIN32)
#include <windows.h>
#include <psapi.h>
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#include <sys/resource.h>
#if defined(__APPLE__) && defined(__MACH__)
#include <mach/mach.h>
#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
#include <fcntl.h>
#include <procfs.h>
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
#include <stdio.h>
#endif
#else
#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
#endif
/**
* Returns the peak (maximum so far) resident set size (physical
* memory use) measured in bytes, or zero if the value cannot be
* determined on this OS.
*/
size_t getPeakRSS( )
{
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
return (size_t)info.PeakWorkingSetSize;
#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
/* AIX and Solaris ------------------------------------------ */
struct psinfo psinfo;
int fd = -1;
if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 )
return (size_t)0L; /* Can't open? */
if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) )
{
close( fd );
return (size_t)0L; /* Can't read? */
}
close( fd );
return (size_t)(psinfo.pr_rssize * 1024L);
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
/* BSD, Linux, and OSX -------------------------------------- */
struct rusage rusage;
getrusage( RUSAGE_SELF, &rusage );
#if defined(__APPLE__) && defined(__MACH__)
return (size_t)rusage.ru_maxrss;
#else
return (size_t)(rusage.ru_maxrss * 1024L);
#endif
#else
/* Unknown OS ----------------------------------------------- */
return (size_t)0L; /* Unsupported. */
#endif
}
/**
* Returns the current resident set size (physical memory use) measured
* in bytes, or zero if the value cannot be determined on this OS.
*/
size_t getCurrentRSS( )
{
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
PROCESS_MEMORY_COUNTERS info;
GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
return (size_t)info.WorkingSetSize;
#elif defined(__APPLE__) && defined(__MACH__)
/* OSX ------------------------------------------------------ */
struct mach_task_basic_info info;
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
(task_info_t)&info, &infoCount ) != KERN_SUCCESS )
return (size_t)0L; /* Can't access? */
return (size_t)info.resident_size;
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
/* Linux ---------------------------------------------------- */
long rss = 0L;
FILE* fp = NULL;
if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
return (size_t)0L; /* Can't open? */
if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
{
fclose( fp );
return (size_t)0L; /* Can't read? */
}
fclose( fp );
return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);
#else
/* AIX, BSD, Solaris, and Unknown OS ------------------------ */
return (size_t)0L; /* Unsupported. */
#endif
}
Usage
用法
size_t currentSize = getCurrentRSS( );
size_t peakSize = getPeakRSS( );
For more discussion, check the web site, it also provides a function to get the physical memory size of a system.
有关更多讨论,请查看网站,它还提供了获取系统物理内存大小的功能。
回答by ?οδεMεδι?
Based on Don W's solution, with fewer variables.
基于 Don W 的解决方案,变量更少。
void process_mem_usage(double& vm_usage, double& resident_set)
{
vm_usage = 0.0;
resident_set = 0.0;
// the two fields we want
unsigned long vsize;
long rss;
{
std::string ignore;
std::ifstream ifs("/proc/self/stat", std::ios_base::in);
ifs >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
>> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
>> ignore >> ignore >> vsize >> rss;
}
long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
vm_usage = vsize / 1024.0;
resident_set = rss * page_size_kb;
}
回答by jtpereyda
I was looking for a Linux app to measure maximum memory used. valgrind is an excellent tool, but was giving me more information than I wanted. tstimeseemed to be the best tool I could find. It measures "highwater" memory usage (RSS and virtual). See this answer.
我正在寻找一个 Linux 应用程序来测量使用的最大内存。valgrind 是一个很好的工具,但它给了我比我想要的更多的信息。tstime似乎是我能找到的最好的工具。它测量“highwater”内存使用情况(RSS 和虚拟)。看到这个答案。