// @(#)root/memstat:$Id: TMemStat.cxx 37063 2010-11-29 13:00:55Z brun $ // Author: Anar Manafov (A.Manafov@gsi.de) and Rene Brun 23/09/2010 /************************************************************************* * Copyright (C) 1995-2010, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ //___________________________________________________________________________ // TMemStat records all the calls to malloc and free and write a TTree // with the position where the memory is allocated/freed , as well as // the number of bytes. // // To use the class TMemStat, add the following statement at the beginning // of your script or program // TMemStat mm("gnubuiltin"); // or in an interactive session do something like: // root > TMemStat mm("gnubuiltin"); // root > .x somescript.C // root > .q // // another (may be more practical way) is to modify $ROOTSYS/etc/system.rootrc // and activate the variable // Root.TMemStat: 1 // // The file collected by TMemStat is named memstat_ProcessID and can be analyzed and results shown // by executing the static function Show. // When TMemStat is active it recors every call to malloc/free in a ROOT Tree. // You must be careful when running jobs with many millions (or more) of calls // to malloc/free because the generated Tree may become very large. // The TMemStat constructor TMemStat(const char* system, Int_t buffersize, Int_t maxcalls) // has its 3 arguments optional: // -system refers to the internal algorithm to compute the back traces. // the recommended value is "gnubuiltin" // -buffersize is the number of calls to malloc or free that can be stored in one memory buffer. // when the buffer is full, the calls to malloc/free pointing to the same location // are eliminated and not written to the final Tree. The default value 100000 // is such that between 50 and 90% of the calls are eliminated depending on the application. // You can set buffersize <=1 to keep every single call to malloc/free. // -maxcalls can set a limit for the maximum number of calls to be registered in the Tree. // The default value is 5000000. // The 3 arguments can be set in $ROOTSYS/etc/system.rootrc // Root.TMemStat.system gnubuiltin // Root.TMemStat.buffersize 100000 // Root.TMemStat.maxcalls 5000000 // // TMemStat::Show creates 3 canvases. // -In canvas1 it displays a dynamic histogram showing for pages (10 kbytes by default) // the percentage of the page used. // A summary pave shows the total memory still in use when the TMemStat object // goes out of scope and the average occupancy of the pages. // The average occupancy gives a good indication of the memory fragmentation. // // -In canvas2 it displays the histogram of memory leaks in decreasing order. // when moving the mouse on this canvas, a tooltip shows the backtrace for the leak // in the bin below the mouse. // // -In canvas3 it displays the histogram of the nbigleaks largest leaks (default is 20) // for each leak, the number of allocs and average alloc size is shown. // // // Simply do: // root > TMemStat::Show() // or specifying arguments // root > TMemStat::Show(0.1,20,"mydir/mymemstat.root"); // // The first argument to Show is the percentage of the time of the original job // that produced the file after which the display is updated. By default update=0.1, // ie 10 time intervals will be shown. // The second argument is nbigleaks. // The third argument is the imput file name (result of TMemStat). // If this argument is omitted, Show will take the most recent file // generated by TMemStat. // // You can restrict the address range to be analyzed via TMemStatShow::SetAddressRange // You can restrict the entry range to be analyzed via TMemStatShow::SetEntryRange // //___________________________________________________________________________ #include "TROOT.h" #include "TDirectory.h" #include "TMemStat.h" #include "TMemStatBacktrace.h" #include "TMemStatMng.h" #include "TMemStatHelpers.h" ClassImp(TMemStat) using namespace std; using namespace memstat; _INIT_TOP_STACK; //______________________________________________________________________________ TMemStat::TMemStat(Option_t* option, Int_t buffersize, Int_t maxcalls): fIsActive(kFALSE) { // Supported options: // "gnubuiltin" - if declared, then MemStat will use gcc build-in function, // otherwise glibc backtrace will be used // // Note: Currently MemStat uses a hard-coded output file name (for writing) = "memstat.root"; // It marks the highest used stack address. _GET_CALLER_FRAME_ADDR; //preserve context. When exiting will restore the current directory TDirectory::TContext context(gDirectory); Bool_t useBuiltin = kTRUE; // Define string in a scope, so that the deletion of it will be not recorded by YAMS { string opt(option); transform(opt.begin(), opt.end(), opt.begin(), memstat::ToLower_t()); useBuiltin = (opt.find("gnubuiltin") != string::npos) ? kTRUE : kFALSE; } TMemStatMng::GetInstance()->SetUseGNUBuiltinBacktrace(useBuiltin); TMemStatMng::GetInstance()->SetBufferSize(buffersize); TMemStatMng::GetInstance()->SetMaxCalls(maxcalls); TMemStatMng::GetInstance()->Enable(); // set this variable only if "NEW" mode is active fIsActive = kTRUE; } //______________________________________________________________________________ TMemStat::~TMemStat() { //destructor if (fIsActive) { TMemStatMng::GetInstance()->Disable(); TMemStatMng::GetInstance()->Close(); } } //______________________________________________________________________________ void TMemStat::Close() { //close the TMemStat manager TMemStatMng::Close(); } //______________________________________________________________________________ void TMemStat::Disable() { //Disable memory statistics TMemStatMng::GetInstance()->Disable(); } //______________________________________________________________________________ void TMemStat::Enable() { //Enable memory statistics TMemStatMng::GetInstance()->Enable(); } //______________________________________________________________________________ void TMemStat::Show(Double_t update, Int_t nbigleaks, const char* fname) { //Show results TString action = TString::Format("TMemStatShow::Show(%g,%d,\"%s\");",update,nbigleaks,fname); gROOT->ProcessLine(action); }