Resource Utilization Info in Unix

As well as timing separate parts of the code, you may need to find memory and other resource usage for separate parts of your program. Generally this is kept in a C struct by the system. The function getr below reads this struct via the standard C library function getrusage() and returns the values in an array. The values returned by getr can be stored and the difference taken from a previous call to find the resources used between calls (except maxrss, the maximum resident size). Returning the values in an array of long ints (8-byte/64-bit integers) allows them to be returned to almost any language: C, C++, Fortran, Java, Matlab, Perl, Python, etc., unlike a C struct, which is only guaranteed to be meaningful in C. If you don't like trying to remember which array entry number is the number of swaps, in all of those languages you can define constants such as
    const long SWAPS = 6;
in C++, or
    integer*8 SWAPS = 7;
in Fortran. The shift of 6 to 7 above is not an error; default indexing in Fortran starts at 1, not 0.

So the function used (called getr here) has to be a C function, since it accesses a C structure. On most machines, if you invoke this from a Fortran subroutine, you will need to add an underscore to the name getr in the C routine below. Interlanguage calling conventions will be covered in more detail later in the course. It is an important aspect of the computer science end of scientific computing, and only recently have Fortran/C/C++ interoperability become a formal part of the language standards.

The getr() function that I use is:

#include <sys/times.h>
#include <sys/types.h>
#include <sys/resource.h>

void getr(double *utime,
          double *stime,
          long counts[15])
{
/*-------------------------------------------------------------
>> Read the system time and resource usage from getrusage(),
>> and return it in a format suitable for using in a Fortran
>> routine. The fields in the array resources have the
>> interpretations that match the corresponding ones in the
>> structure rusage of /sys/resource.h:
>>        maxrss   =   maximum resident size so far
>>        ixrss    =   integral shared memory size 
>>        idrss    =   integral unshared data 
>>        isrss    =   integral unshared stack
>>        minflt   =   page reclaims 
>>        majflt   =   page faults 
>>        nswap    =   swaps 
>>        inblock  =   block input operations 
>>        oublock  =   block output operations 
>>        msgsnd   =   IPC messages sent 
>>        msgrcv   =   IPC messages received 
>>        nsignals =   signals received 
>>        nvcsw    =   voluntary context switches 
>>        nivcsw   =   involuntary context switches 
>> The returned array has two additional slots for 
>> possible future extensions.
-------------------------------------------------------------*/
     struct rusage resources;
     struct timeval rutime;
     struct timeval rstime;
     int who = RUSAGE_SELF;
     int ierr;
     int i;

     ierr = getrusage (who, &resources);

/* ---------------------------------------- */
/* In case of error, return garbage values: */
/* ---------------------------------------- */
     if (ierr != 0) 
      { *utime = -1.0;
        *stime = -1.0;
        for (i = 0; i < 15; i++) counts[i] = -1;
        return; }

/* ----------------------------------- */
/* Unpack structure to return as array */
/* ----------------------------------- */
      *utime = (double) resources.ru_utime.tv_sec
               + 1.0e-6 * (double) resources.ru_utime.tv_usec;
      *stime = (double) resources.ru_stime.tv_sec
               + 1.0e-6 * (double) resources.ru_stime.tv_usec;
      counts[0]  = resources.ru_maxrss;     /* maximum resident set size */
      counts[1]  = resources.ru_ixrss;      /* integral shared memory size */
      counts[2]  = resources.ru_idrss;      /* integral unshared data size */
      counts[3]  = resources.ru_isrss;      /* integral unshared stack size */
      counts[4]  = resources.ru_minflt;     /* page reclaims */
      counts[5]  = resources.ru_majflt;     /* page faults */
      counts[6]  = resources.ru_nswap;      /* swaps */
      counts[7]  = resources.ru_inblock;    /* block input operations */
      counts[8]  = resources.ru_oublock;    /* block output operations */
      counts[9]  = resources.ru_msgsnd;     /* messages sent */
      counts[10] = resources.ru_msgrcv;     /* messages received */
      counts[11] = resources.ru_nsignals;   /* signals received */
      counts[12] = resources.ru_nvcsw;      /* voluntary context switches */
      counts[13] = resources.ru_nivcsw;     /* involuntary context switches */
      return; }

Beware, however, that Linux does not implement all of those fields. Use "man getrusage" to see what is currently handled.