C++ Programming - System-Specific

Index

If you notice any mistakes or have additions, click here.

MemoryUsed() Function

There is no portable function to measure memory used by a program. The best measurement is how much memory malloc() has allocated (which GLIB provides). A second-best measurement is how many resident pages are used. getrusage(), which is poorly implemented even on FreeBSD and Linux, is practically useless for measuring memory.


#if OS_APPLE
#   include <mach/mach_init.h>
#   include <mach/task.h>
#elif OS_UNIX
#   include <sstream>
#   include <sys/time.h>
#   include <time.h>
#   if __GLIBC__  // GNU Linux
#       include <malloc.h>
#   elif OS_FREEBSD
#       include <sys/file.h>
#       include <sys/sysctl.h>
#       include <sys/user.h>
#       include <kvm.h>
#   endif
#endif

/*****************************************************************************
 * Return total amount of bytes allocated.
 *****************************************************************************/
unsigned long
MemoryUsed( void )
{
#if __GLIBC__  // GNU Linux

    // Per delorie.com:
    // Example:
    // struct mallinfo info = mallinfo();
    // printf("Memory in use: %d bytes\n", info.usmblks + info.uordblks);
    // printf("Total heap size: %d bytes\n", info.arena);
    struct mallinfo meminfo;
    meminfo = mallinfo();
  //return meminfo.arena;
    return meminfo.usmblks + meminfo.uordblks;

#elif OS_APPLE

    // Use Mach functions.
    task_basic_info        machInfo  = { 0 };
    mach_port_t            machTask  = mach_task_self();
    mach_msg_type_number_t machCount = TASK_BASIC_INFO_COUNT;
    if ( task_info( machTask, TASK_BASIC_INFO, reinterpret_cast<task_info_t>(&machInfo), &machCount ) == KERN_SUCCESS )
        return machInfo.resident_size;
    else
        return 0;  // error

#elif OS_FREEBSD

    // getrusage() doesn't work right on FreeBSD and anyway it has
    // a horrible convoluted interface for measuring memory.
    // kvm is reliable but does require linking with the kvm library.
    PERSISTENT kvm_t* kd = kvm_open( NULL, "/dev/null", NULL, O_RDONLY, "kvm_open" );  // open once
    if ( kd != NULL )
    {
        // Use FreeBSD kvm function to get the size of resident pages (RSS).
        int procCount = 0;
        struct kinfo_proc* kp = kvm_getprocs( kd, KERN_PROC_PID, getpid(), &procCount );  // do not free returned struct
        if ( (kp != NULL) and (procCount >= 1) )    // in case multiple threads have the same PID
            return kp->ki_rssize * getpagesize();   // success
    }
    return 0;  // failed

#else

    return 0;  // unsupported

#endif
}

home
© 2012 Jim Brooks
Last modified: Wed Apr 21 11:16:59 CDT 2010