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.