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 and returns 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). The reason for returning the values in an array of "long ints" is so that they can 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.

So getr has to be a C routine, 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 there are few standards.

#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; }

Recall also the the PAPI Project; that or a related universal API is likely to be the tool of the future for accessing this kind of information.