Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

LeaMemMonitor.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // $Id: LeaMemMonitor.cxx,v 1.6 2007/02/08 17:03:42 rhatcher Exp $
00004 //
00005 // functions for inquiring about and printing current memory usage
00006 // Linux specific!!!
00007 //
00009 #include "LeakChecker/LeaMemMonitor.h"
00010 
00011 #include <sys/types.h>
00012 #include <stdio.h>
00013 #include <fcntl.h>
00014 #include <unistd.h>
00015 #include <stdlib.h>
00016 #include <time.h>
00017 #include <sys/stat.h>
00018 
00019 #define PROCFS "/proc"
00020 #define PROCSTATUS "/proc/self/status"
00021 
00022 #include "MessageService/MsgService.h"
00023 CVSID("$Id: LeaMemMonitor.cxx,v 1.6 2007/02/08 17:03:42 rhatcher Exp $");
00024 
00025 void LeaMemMonitor::FillMemStat(LeaMemMonitor::memstat_t& result)
00026 {
00027 // use proc pseudo-file system to determine process memory usage
00028    
00029 #ifndef linux
00030    MSG("Lea",Msg::kFatal)
00031       << "Not supported for any OS other than Linux" << endl;
00032    result.ms_total.mu_sizex = 0; // use result to avoid unused warning
00033 #else
00034    char buffer[4096+1];
00035 
00036    int fd = open(PROCSTATUS,O_RDONLY);
00037    int len = read(fd,buffer,sizeof(buffer)-1);
00038    close(fd);
00039    buffer[len] = '\0';
00040    
00041    // skip 9 lines so scanf can sync
00042    int nskip = 0;
00043    char *p = buffer;
00044    char *pend = buffer+len;
00045    while (p<pend) {
00046       if (*p == '\n') nskip++;
00047       p++;
00048       if (nskip == 10) break;
00049    }   
00050 
00051    // interpret what should be there
00052    int nexpect = 14;
00053    int ndatum = sscanf(p,"VmSize: %u %cB \
00054                           VmLck: %u %cB \
00055                           VmRSS: %u %cB \
00056                           VmData: %u %cB \
00057                           VmStk: %u %cB \
00058                           VmExe: %u %cB \
00059                           VmLib: %u %cB",
00060                        &result.ms_total.mu_sizex,&result.ms_total.mu_sizeu,
00061                        &result.ms_lck.mu_sizex,&result.ms_lck.mu_sizeu,
00062                        &result.ms_rss.mu_sizex,&result.ms_rss.mu_sizeu,
00063                        &result.ms_data.mu_sizex,&result.ms_data.mu_sizeu,
00064                        &result.ms_stk.mu_sizex,&result.ms_stk.mu_sizeu,
00065                        &result.ms_exe.mu_sizex,&result.ms_exe.mu_sizeu,
00066                        &result.ms_lib.mu_sizex,&result.ms_lib.mu_sizeu);
00067 
00068    if (ndatum != nexpect)
00069       MSG("Lea",Msg::kWarning)
00070          << " sscanf only returned " << ndatum << " of "
00071          << nexpect << " items " << endl;
00072    
00073    // interpret units back to bytes
00074    LeaMemMonitor::CalcBytes(result.ms_total);
00075    LeaMemMonitor::CalcBytes(result.ms_lck);
00076    LeaMemMonitor::CalcBytes(result.ms_rss);
00077    LeaMemMonitor::CalcBytes(result.ms_data);
00078    LeaMemMonitor::CalcBytes(result.ms_stk);
00079    LeaMemMonitor::CalcBytes(result.ms_exe);
00080    LeaMemMonitor::CalcBytes(result.ms_lib);
00081 
00082 #endif
00083 
00084 }
00085 
00086 void LeaMemMonitor::PrintMemStat(const char* tag)
00087 {
00088 // use proc pseudo-file system to determine process memory usage
00089 // print the results
00090 
00091 #ifndef linux
00092    MSG("Lea",Msg::kFatal)
00093       << "Not supported for any OS other than Linux: " 
00094       << tag
00095       << endl;
00096 #else
00097    memstat_t result;
00098    LeaMemMonitor::FillMemStat(result);
00099 
00100    /* This reasonable looking code causes gcc3.0.2 to dump core during
00101     compile (Internal error #980715). So, I replaced this with the
00102     less elegant code in the if statement...  */
00103    /*
00104      MSG("Lea",Msg::kInfo)
00105      << ( (tag) ? tag : "" )     // protect against missing tag
00106      << ( (tag) ? endl : flush ) // stats on separate line if tag given
00107    */
00108    if (tag) MSG("Lea",Msg::kInfo) << tag << endl;
00109    MSG("Lea",Msg::kInfo)
00110       << "Memory:"
00111       << " Total " << result.ms_total.mu_sizex << result.ms_total.mu_sizeu
00112 //      << ", Lck "   << result.ms_lck.mu_sizex   << result.ms_lck.mu_sizeu
00113       << ", RSS "   << result.ms_rss.mu_sizex   << result.ms_rss.mu_sizeu
00114       << ", Data "  << result.ms_data.mu_sizex  << result.ms_data.mu_sizeu
00115       << ", Stack " << result.ms_stk.mu_sizex   << result.ms_stk.mu_sizeu
00116       << ", Exe "   << result.ms_exe.mu_sizex   << result.ms_exe.mu_sizeu
00117       << ", Lib "   << result.ms_lib.mu_sizex   << result.ms_lib.mu_sizeu
00118       << endl;
00119 #endif
00120 }
00121 
00122 void LeaMemMonitor::CalcBytes(memusage_t& usage)
00123 {
00124    switch (usage.mu_sizeu) {
00125    case 'k':
00126    case 'K':
00127       usage.mu_size = 1024 * usage.mu_sizex;
00128       break;
00129    case 'm':
00130    case 'M':
00131       usage.mu_size = 1024 * 1024 * usage.mu_sizex;
00132       break;
00133    default:
00134       usage.mu_size = usage.mu_sizex;
00135       MSG("Lea",Msg::kWarning)
00136          << "unit designator \"" << usage.mu_sizeu 
00137          << "\" not recognized" << endl;
00138       
00139    }
00140 }

Generated on Mon Feb 15 11:06:51 2010 for loon by  doxygen 1.3.9.1