Measuring Memory Usage
An important (or at least interesting) part of programming plays the measuring of the current memory consumption of a program, is it to detect memory leaks or to check whether a desired complexity holds.
Although one could use the mallinfo function which comes
along with malloc, I found it more accurate to rely on certain functionality
provided by the operating system itself. Especially, if one uses a malloc-replacement
mallinfo might not always take account of all allocations, e.g. via
mmap. This also holds for the alternative method of doing a sbrk(0)
call and evaluating the returned value.
Unfortunately, the kind of reading the current memory usage is different
on the various operating systems. The following list provides an overview
of what I collected over the last couple of years and which serves me
quite well. Each code-snippet puts the memory consumption into a variable
named mem_size of type unsigned long.
Linux
In Linux the current memory consumption is available due to /proc-filesystem. In particular, the first entry in /proc/<pid>/statm holds the number of pages allocated by the corresponding process.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
char buf[256];
FILE * file;
unsigned int pages;
snprintf( buf, sizeof(buf), "/proc/%d/statm", (unsigned int) getpid() );
if ((file = fopen( buf, "r" )) == NULL)
{
perror( "open" );
return 0;
}
fgets( buf, sizeof(buf), file );
fclose( file );
sscanf( buf, "%u", & pages );
mem_size = ((unsigned long) pages) * ((unsigned long) getpagesize());
Solaris
Even simpler is the situation under Solaris. Again the /proc-filesystem serves the purpose. This time, the file /proc/<pid>/as represents the address-space of the process and therefore, the size of this file equals the current memory consumption.
Though one has to distinguish between 32- and 64-bit computing. In the latter
case the stat64 functions has to be used.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#if defined (__sparc_v9__) || defined (__sparcv9)
struct stat64 stat_buf;
char buf[256];
snprintf( buf, sizeof(buf), "/proc/%d/as", (unsigned int) getpid() );
if ( stat64( buf, & stat_buf ) < 0 )
perror( "stat" );
mem_size = stat_buf.st_size;
#else
struct stat stat_buf;
char buf[256];
snprintf( buf, sizeof(buf), "/proc/%d/as", (unsigned int) getpid() );
if ( stat( buf, & stat_buf ) < 0 )
perror( "stat" );
mem_size = stat_buf.st_size;
#endif
Tru64
The following piece of code stems from some friendly guy at Compaq/HP
which send it to me when we did some benchmarking on Alpha-machines
(those were the days ;-) . Anyway, it reads the number of pages allocated
by the process from the /proc-filesystem with a ioctl-call.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/procfs.h>
char buf[256];
int file;
struct prpsinfo * prpsinfo;
struct prpsinfo arrayprpsinfo[32];
prpsinfo = arrayprpsinfo;
snprintf( buf, sizeof(buf), "/proc/%d", (unsigned int) getpid() );
if ((file = open( buf, O_RDONLY, 0555 )) < 0)
perror( "open" );
if ((ioctl(file, PIOCPSINFO, prpsinfo)) == -1)
perror( "ioctl" );
close( file );
mem_size = prpsinfo->pr_size * getpagesize();
AIX
Information about a process is put on AIX into the file /proc/<pid>/psinfo. By reading the content of this file one gets access to various data including the memory consupmtion.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/procfs.h>
char buf[256];
int file;
struct psinfo psi;
snprintf( buf, sizeof(buf), "/proc/%d/psinfo", (unsigned int) getpid() );
if ((file = open( buf, O_RDONLY, 0555 )) < 0)
perror( "open" );
if ( read( file, & psi, sizeof(psi) ) < 0 )
perror( "read" );
close( file );
mem_size = psi.pr_size;
HP-UX
In contrast to the systems so far, on HP-UX the wanted information is not read from
the /proc-filesystem, but is access due to a special function: pstat_getproc.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/pstat.h>
struct pst_status pst;
if ( pstat_getproc( & pst, sizeof(pst), 0, getpid() ) != -1 )
{
mem_size = pst.pst_dsize + pst.pst_tsize + pst.pst_ssize + pst.pst_mmsize;
mem_size *= getpagesize();
}
else
perror( "pstat_getproc" );
To Be Done
What's still missing are algorithms for BSD-systems. I pressume I have to use some KVM-related functions. But as far as I know I need some superuser-privileges to access the data in question. Maybe I have to read some more code examples or someone sends me a nice hint.
All systems so far are Unices. I'm not sure if I want to include different operating systems. Especially the one we all don't like. But I'm afraid, sooner or later I have to.