00001 // @(#)root/memstat:$Id: TMemStat.cxx 37063 2010-11-29 13:00:55Z brun $ 00002 // Author: Anar Manafov (A.Manafov@gsi.de) and Rene Brun 23/09/2010 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2010, Rene Brun and Fons Rademakers. * 00006 * All rights reserved. * 00007 * * 00008 * For the licensing terms see $ROOTSYS/LICENSE. * 00009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00010 *************************************************************************/ 00011 00012 //___________________________________________________________________________ 00013 // TMemStat records all the calls to malloc and free and write a TTree 00014 // with the position where the memory is allocated/freed , as well as 00015 // the number of bytes. 00016 // 00017 // To use the class TMemStat, add the following statement at the beginning 00018 // of your script or program 00019 // TMemStat mm("gnubuiltin"); 00020 // or in an interactive session do something like: 00021 // root > TMemStat mm("gnubuiltin"); 00022 // root > .x somescript.C 00023 // root > .q 00024 // 00025 // another (may be more practical way) is to modify $ROOTSYS/etc/system.rootrc 00026 // and activate the variable 00027 // Root.TMemStat: 1 00028 // 00029 // The file collected by TMemStat is named memstat_ProcessID and can be analyzed and results shown 00030 // by executing the static function Show. 00031 // When TMemStat is active it recors every call to malloc/free in a ROOT Tree. 00032 // You must be careful when running jobs with many millions (or more) of calls 00033 // to malloc/free because the generated Tree may become very large. 00034 // The TMemStat constructor TMemStat(const char* system, Int_t buffersize, Int_t maxcalls) 00035 // has its 3 arguments optional: 00036 // -system refers to the internal algorithm to compute the back traces. 00037 // the recommended value is "gnubuiltin" 00038 // -buffersize is the number of calls to malloc or free that can be stored in one memory buffer. 00039 // when the buffer is full, the calls to malloc/free pointing to the same location 00040 // are eliminated and not written to the final Tree. The default value 100000 00041 // is such that between 50 and 90% of the calls are eliminated depending on the application. 00042 // You can set buffersize <=1 to keep every single call to malloc/free. 00043 // -maxcalls can set a limit for the maximum number of calls to be registered in the Tree. 00044 // The default value is 5000000. 00045 // The 3 arguments can be set in $ROOTSYS/etc/system.rootrc 00046 // Root.TMemStat.system gnubuiltin 00047 // Root.TMemStat.buffersize 100000 00048 // Root.TMemStat.maxcalls 5000000 00049 // 00050 // TMemStat::Show creates 3 canvases. 00051 // -In canvas1 it displays a dynamic histogram showing for pages (10 kbytes by default) 00052 // the percentage of the page used. 00053 // A summary pave shows the total memory still in use when the TMemStat object 00054 // goes out of scope and the average occupancy of the pages. 00055 // The average occupancy gives a good indication of the memory fragmentation. 00056 // 00057 // -In canvas2 it displays the histogram of memory leaks in decreasing order. 00058 // when moving the mouse on this canvas, a tooltip shows the backtrace for the leak 00059 // in the bin below the mouse. 00060 // 00061 // -In canvas3 it displays the histogram of the nbigleaks largest leaks (default is 20) 00062 // for each leak, the number of allocs and average alloc size is shown. 00063 // 00064 // 00065 // Simply do: 00066 // root > TMemStat::Show() 00067 // or specifying arguments 00068 // root > TMemStat::Show(0.1,20,"mydir/mymemstat.root"); 00069 // 00070 // The first argument to Show is the percentage of the time of the original job 00071 // that produced the file after which the display is updated. By default update=0.1, 00072 // ie 10 time intervals will be shown. 00073 // The second argument is nbigleaks. 00074 // The third argument is the imput file name (result of TMemStat). 00075 // If this argument is omitted, Show will take the most recent file 00076 // generated by TMemStat. 00077 // 00078 // You can restrict the address range to be analyzed via TMemStatShow::SetAddressRange 00079 // You can restrict the entry range to be analyzed via TMemStatShow::SetEntryRange 00080 // 00081 //___________________________________________________________________________ 00082 00083 #include "TROOT.h" 00084 #include "TDirectory.h" 00085 #include "TMemStat.h" 00086 #include "TMemStatBacktrace.h" 00087 #include "TMemStatMng.h" 00088 #include "TMemStatHelpers.h" 00089 00090 ClassImp(TMemStat) 00091 00092 using namespace std; 00093 using namespace memstat; 00094 00095 _INIT_TOP_STACK; 00096 00097 //______________________________________________________________________________ 00098 TMemStat::TMemStat(Option_t* option, Int_t buffersize, Int_t maxcalls): fIsActive(kFALSE) 00099 { 00100 // Supported options: 00101 // "gnubuiltin" - if declared, then MemStat will use gcc build-in function, 00102 // otherwise glibc backtrace will be used 00103 // 00104 // Note: Currently MemStat uses a hard-coded output file name (for writing) = "memstat.root"; 00105 00106 // It marks the highest used stack address. 00107 _GET_CALLER_FRAME_ADDR; 00108 00109 //preserve context. When exiting will restore the current directory 00110 TDirectory::TContext context(gDirectory); 00111 00112 Bool_t useBuiltin = kTRUE; 00113 // Define string in a scope, so that the deletion of it will be not recorded by YAMS 00114 { 00115 string opt(option); 00116 transform(opt.begin(), opt.end(), opt.begin(), 00117 memstat::ToLower_t()); 00118 00119 useBuiltin = (opt.find("gnubuiltin") != string::npos) ? kTRUE : kFALSE; 00120 } 00121 00122 TMemStatMng::GetInstance()->SetUseGNUBuiltinBacktrace(useBuiltin); 00123 TMemStatMng::GetInstance()->SetBufferSize(buffersize); 00124 TMemStatMng::GetInstance()->SetMaxCalls(maxcalls); 00125 TMemStatMng::GetInstance()->Enable(); 00126 // set this variable only if "NEW" mode is active 00127 fIsActive = kTRUE; 00128 00129 } 00130 00131 //______________________________________________________________________________ 00132 TMemStat::~TMemStat() 00133 { 00134 //destructor 00135 if (fIsActive) { 00136 TMemStatMng::GetInstance()->Disable(); 00137 TMemStatMng::GetInstance()->Close(); 00138 } 00139 } 00140 00141 //______________________________________________________________________________ 00142 void TMemStat::Close() 00143 { 00144 //close the TMemStat manager 00145 TMemStatMng::Close(); 00146 } 00147 00148 //______________________________________________________________________________ 00149 void TMemStat::Disable() 00150 { 00151 //Disable memory statistics 00152 TMemStatMng::GetInstance()->Disable(); 00153 } 00154 00155 //______________________________________________________________________________ 00156 void TMemStat::Enable() 00157 { 00158 //Enable memory statistics 00159 TMemStatMng::GetInstance()->Enable(); 00160 } 00161 00162 //______________________________________________________________________________ 00163 void TMemStat::Show(Double_t update, Int_t nbigleaks, const char* fname) 00164 { 00165 //Show results 00166 TString action = TString::Format("TMemStatShow::Show(%g,%d,\"%s\");",update,nbigleaks,fname); 00167 gROOT->ProcessLine(action); 00168 }