Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
memstatExample.C File Reference

Detailed Description

Script post-processing the file generated by TMemStat (default memstat.root)

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

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.

This script creates 2 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.

The script can be executed simply as

root > .x memstat.C (or via ACLIC .x memstat.C+ )
Double_t x[n]
Definition legend1.C:17

or specifying arguments

root > .x memstat.C+(0.01,"mydir/mymemstat.root");

The first argument to the script is the percentage of the time of the original job that produced the file after which the display is updated. By default update=0.01, ie 100 time intervals will be shown. The second argument is the input file name (result of TMemStat). If this argument is omitted, the script will take the most recent file generated by TMemStat.

Analyzing file: (null)
Cannot open file (null)
#include "TMath.h"
#include "TFile.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TStyle.h"
#include "TH1.h"
#include "TPaveText.h"
#include "TPaveLabel.h"
#include "TSystem.h"
#include "TGClient.h"
#include "TGToolTip.h"
#include "TRootCanvas.h"
TTree *T;
TH1D *halloc, *hfree;
TH1I *hleaks, *hentry;
TGToolTip *gTip = 0;
TObjArray *btidlist=0;
Double_t *V1, *V2, *V3, *V4;
void EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected);
void memstatExample(double update=0.01, const char* fname="*") {
// Open the memstat data file, then call TTree::Draw to precompute
// the arrays of positions and nbytes per entry.
// update is the time interval in the data file in seconds after which
// the display is updated. For example is the job producing the memstat.root file
// took 100s to execute, an update of 0.1s will generate 1000 time views of
// the memory use.
// if fname=="*" (default), the most recent file memstat*.root will be taken.
if (!fname || strlen(fname) <5 || strstr(fname,"*")) {
//take the most recent file memstat*.root
s = gSystem->GetFromPipe("ls -lrt memstat*.root");
Int_t ns = s.Length();
fname = strstr(s.Data()+ns-25,"memstat");
}
printf("Analyzing file: %s\n",fname);
f = TFile::Open(fname);
if (!f) {
printf("Cannot open file %s\n",fname);
return;
}
T = (TTree*)f->Get("T");
if (!T) {
printf("cannot find the TMemStat TTree named T in file %s\n",fname);
return;
}
if (update <= 0) {
printf("Illegal update value %g, changed to 0.01\n",update);
update = 0.01;
}
if (update < 0.001) printf("Warning update parameter is very small, processing may be slow\n");
Long64_t nentries = T->GetEntries();
T->SetEstimate(nentries+10);
Long64_t nsel = T->Draw("pos:nbytes:time:btid","","goff");
//now we compute the best binning for the histogram
Int_t nbytes;
Double_t pos;
V1 = T->GetV1();
V2 = T->GetV2();
V3 = T->GetV3();
V4 = T->GetV4();
Long64_t imean = (Long64_t)TMath::Mean(nsel,V1);
Long64_t irms = (Long64_t)TMath::RMS(nsel,V1);
//Long64_t bw = 10000;
Long64_t bw = 1000;
imean = imean - imean%bw;
irms = irms -irms%bw;
Int_t nbins = Int_t(4*irms/bw);
Long64_t ivmin = imean -bw*nbins/2;
Long64_t ivmax = ivmin+bw*nbins;
if (ivmax > 2000000000 && ivmin <2000000000) {
//the data set has been likely generated on a 32 bits machine
//we are mostly interested by the small allocations, so we select
//only values below 2 GBytes
printf("memory locations above 2GBytes will be ignored\n");
nsel = T->Draw("pos:nbytes:time:btid","pos <2e9","goff");
V1 = T->GetV1();
V2 = T->GetV2();
V3 = T->GetV3();
V4 = T->GetV4();
imean = (Long64_t)TMath::Mean(nsel,V1);
irms = (Long64_t)TMath::RMS(nsel,V1);
bw = 10000;
imean = imean - imean%bw;
irms = irms -irms%bw;
nbins = Int_t(4*irms/bw);
ivmin = imean -bw*nbins/2;
ivmax = ivmin+bw*nbins;
}
update *= 0.0001*V3[nsel-1]; //convert time per cent in seconds
Long64_t nvm = Long64_t(ivmax-ivmin+1);
Long64_t *nbold = new Long64_t[nvm];
Int_t *ientry = new Int_t[nvm];
memset(nbold,0,nvm*8);
Double_t dv = (ivmax-ivmin)/nbins;
h = new TH1D("h",Form("%s;pos;per cent of pages used",fname),nbins,ivmin,ivmax);
TAxis *axis = h->GetXaxis();
h->SetFillColor(kRed);
h->SetMinimum(0);
h->SetMaximum(100);
halloc = new TH1D("halloc",Form("%s;pos;number of mallocs",fname),nbins,ivmin,ivmax);
hfree = new TH1D("hfree", Form("%s;pos;number of frees",fname),nbins,ivmin,ivmax);
//open a canvas and draw the empty histogram
TCanvas *c1 = new TCanvas("c1","c1",1200,600);
c1->SetFrameFillColor(kYellow-3);
c1->SetGridx();
c1->SetGridy();
h->Draw();
//create a TPaveText to show the summary results
TPaveText *pvt = new TPaveText(.5,.9,.75,.99,"brNDC");
pvt->Draw();
//create a TPaveLabel to show the time
TPaveLabel *ptime = new TPaveLabel(.905,.7,.995,.76,"time","brNDC");
ptime->SetFillColor(kYellow-3);
ptime->Draw();
//draw producer identifier
TNamed *named = (TNamed*)T->GetUserInfo()->FindObject("SysInfo");
TText tmachine;
tmachine.SetTextSize(0.02);
tmachine.SetNDC();
if (named) tmachine.DrawText(0.01,0.01,named->GetTitle());
//start loop on selected rows
Int_t bin,nb=0,j;
Long64_t ipos;
Double_t dbin,rest,time;
Double_t updateLast = 0;
Int_t nleaks = 0;
Int_t i;
for (i=0;i<nsel;i++) {
pos = V1[i];
ipos = (Long64_t)(pos-ivmin);
nbytes = (Int_t)V2[i];
time = 0.0001*V3[i];
bin = axis->FindBin(pos);
if (bin<1 || bin>nbins) continue;
dbin = axis->GetBinUpEdge(bin)-pos;
if (nbytes > 0) {
halloc->Fill(pos);
if (dbin > nbytes) dbin = nbytes;
//fill bytes in the first page
h->AddBinContent(bin,100*dbin/dv);
//fill bytes in full following pages
nb = Int_t((nbytes-dbin)/dv);
if (bin+nb >nbins) nb = nbins-bin;
for (j=1;j<=nb;j++) h->AddBinContent(bin+j,100);
//fill the bytes remaining in last page
rest = nbytes-nb*dv-dbin;
if (rest > 0) h->AddBinContent(bin+nb+1,100*rest/dv);
//we save nbytes at pos. This info will be used when we free this slot
if (nbold[ipos] > 0) printf("reallocating %d bytes (was %lld) at %lld, entry=%d\n",nbytes,nbold[ipos],ipos,i);
if (nbold[ipos] == 0) {
nleaks++;
//save the Tree entry number where we made this allocation
ientry[ipos] = i;
}
nbold[ipos] = nbytes;
} else {
hfree->Fill(pos);
nbytes = nbold[ipos];
if (bin+nb >nbins) nb = nbins-bin;
nbold[ipos] = 0; nleaks--;
if (nbytes <= 0) continue;
//fill bytes free in the first page
if (dbin > nbytes) dbin = nbytes;
h->AddBinContent(bin,-100*dbin/dv);
//fill bytes free in full following pages
nb = Int_t((nbytes-dbin)/dv);
if (bin+nb >nbins) nb = nbins-bin;
for (j=1;j<=nb;j++) h->AddBinContent(bin+j,-100);
//fill the bytes free in in last page
rest = nbytes-nb*dv-dbin;
if (rest > 0) h->AddBinContent(bin+nb+1,-100*rest/dv);
}
if (time -updateLast > update) {
//update canvas at regular intervals
updateLast = time;
h->SetEntries(i);
c1->Modified();
Double_t mbytes = 0;
Int_t nonEmpty = 0;
for (Int_t k=1;k<nbins;k++) {
w = h->GetBinContent(k);
if (w > 0) {
nonEmpty++;
mbytes += 0.01*w*dv;
}
}
Double_t occupancy = mbytes/(nonEmpty*0.01*dv);
pvt->AddText(Form("memory used = %g Mbytes",mbytes*1e-6));
pvt->AddText(Form("page occupancy = %f per cent",occupancy));
pvt->AddText("(for non empty pages only)");
ptime->SetLabel(Form("%g sec",time));
c1->Update();
}
}
h->SetEntries(nsel);
Int_t nlmax = nleaks;
nleaks += 1000;
Int_t *lindex = new Int_t[nleaks];
Int_t *entry = new Int_t[nleaks];
Int_t *ileaks = new Int_t[nleaks];
nleaks =0;
for (Int_t ii=0;ii<nvm;ii++) {
if (nbold[ii] > 0) {
ileaks[nleaks] = (Int_t)nbold[ii];
entry[nleaks] = ientry[ii];
nleaks++;
if (nleaks > nlmax) break;
}
}
TMath::Sort(nleaks,ileaks,lindex);
hentry = new TH1I("hentry","leak entry index",nleaks,0,nleaks);
hleaks = new TH1I("hleaks","leaks;leak number;nbytes in leak",nleaks,0,nleaks);
for (Int_t k=0;k<nleaks;k++) {
Int_t kk = lindex[k];
i = entry[kk];
hentry->SetBinContent(k+1,i);
hleaks->SetBinContent(k+1,ileaks[kk]);
}
hentry->SetEntries(nleaks);
hleaks->SetEntries(nleaks);
//open a second canvas and draw the histogram with leaks in decreasing order
TCanvas *c2 = new TCanvas("c2","c2",1200,600);
c2->SetFrameFillColor(kCyan-6);
c2->SetGridx();
c2->SetGridy();
c2->SetLogy();
hleaks->SetFillColor(kRed-3);
if (nleaks > 1000) hleaks->GetXaxis()->SetRange(1,1000);
hleaks->Draw();
//draw producer identifier
if (named) tmachine.DrawText(0.01,0.01,named->GetTitle());
//construct the tooltip
TRootCanvas *rc = (TRootCanvas *)c2->GetCanvasImp();
TGMainFrame *frm = dynamic_cast<TGMainFrame *>(rc);
// create the tooltip with a timeout of 250 ms
if (!gTip) gTip = new TGToolTip(gClient->GetDefaultRoot(), frm, "", 250);
c2->Connect("ProcessedEvent(Int_t, Int_t, Int_t, TObject*)",
0, 0, "EventInfo(Int_t, Int_t, Int_t, TObject*)");
}
//______________________________________________________________________
void EventInfo(Int_t event, Int_t px, Int_t , TObject *selected)
{
//draw the tooltip showing the backtrace for the bin at px
if (!gTip) return;
gTip->Hide();
if (event == kMouseLeave)
return;
Double_t xpx = gPad->AbsPixeltoX(px);
Int_t bin = hleaks->GetXaxis()->FindBin(xpx);
if (bin <=0 || bin > hleaks->GetXaxis()->GetNbins()) return;
Int_t nbytes = (Int_t)hleaks->GetBinContent(bin);
Int_t entry = (Int_t)hentry->GetBinContent(bin);
Int_t btid = (Int_t)V4[entry];
Double_t time = 0.0001*V3[entry];
TH1I *hbtids = (TH1I*)T->GetUserInfo()->FindObject("btids");
if (!hbtids) return;
if (!btidlist) btidlist = (TObjArray*)T->GetUserInfo()->FindObject("FAddrsList");
if (!btidlist) btidlist = (TObjArray*)f->Get("FAddrsList"); //old memstat files
if (!btidlist) return;
Int_t nbt = (Int_t)hbtids->GetBinContent(btid-1);
TString ttip;
for (Int_t i=0;i<nbt;i++) {
Int_t j = (Int_t)hbtids->GetBinContent(btid+i);
TNamed *nm = (TNamed*)btidlist->At(j);
if (nm==0) break;
char *title = (char*)nm->GetTitle();
Int_t nch = strlen(title);
if (nch < 20) continue;
if (nch > 100) title[100] =0;
const char *bar = strstr(title,"| ");
if (!bar) continue;
if (strstr(bar,"operator new")) continue;
if (strstr(bar,"libMemStat")) continue;
if (strstr(bar,"G__Exception")) continue;
ttip += TString::Format("%2d %s\n",i,bar+1);
}
if (selected) {
TString form1 = TString::Format(" Leak number=%d, leaking %d bytes at entry=%d time=%gseconds\n\n",bin,nbytes,entry,time);
gTip->SetText(TString::Format("%s%s",form1.Data(),ttip.Data() ));
gTip->SetPosition(px+15, 100);
gTip->Reset();
}
}
@ kMouseLeave
Definition Buttons.h:23
#define f(i)
Definition RSha256.hxx:104
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
int Int_t
Definition RtypesCore.h:45
double Double_t
Definition RtypesCore.h:59
long long Long64_t
Definition RtypesCore.h:73
@ kRed
Definition Rtypes.h:66
@ kCyan
Definition Rtypes.h:66
@ kYellow
Definition Rtypes.h:66
#define gClient
Definition TGClient.h:166
int nentries
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition TStyle.h:412
R__EXTERN TSystem * gSystem
Definition TSystem.h:559
#define gPad
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:46
Class to manage histogram axis.
Definition TAxis.h:30
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
Int_t GetNbins() const
Definition TAxis.h:121
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:920
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:528
The Canvas class.
Definition TCanvas.h:23
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition TFile.h:54
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:3997
void Hide()
Hide tool tip window.
void SetPosition(Int_t x, Int_t y)
Set popup position within specified frame (as specified in the ctor).
void SetText(const char *new_text)
Set new tool tip text.
void Reset()
Reset tool tip popup delay timer.
1-D histogram with a double per channel (see TH1 documentation)}
Definition TH1.h:618
1-D histogram with an int per channel (see TH1 documentation)}
Definition TH1.h:534
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition TH1.h:320
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition TH1.cxx:3350
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9062
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition TH1.cxx:3073
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:4993
virtual void SetEntries(Double_t n)
Definition TH1.h:385
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
virtual const char * GetTitle() const
Returns title of object.
Definition TNamed.h:48
An array of TObjects.
Definition TObjArray.h:37
TObject * At(Int_t idx) const
Definition TObjArray.h:166
Mother of all ROOT objects.
Definition TObject.h:37
A Pave (see TPave) with a text centered in the Pave.
Definition TPaveLabel.h:20
virtual void Draw(Option_t *option="")
Draw this pavelabel with its current attributes.
virtual void SetLabel(const char *label)
Definition TPaveLabel.h:41
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
virtual void Draw(Option_t *option="")
Draw this pavetext with its current attributes.
virtual TList * GetListOfLines() const
Definition TPaveText.h:49
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
const char * Data() const
Definition TString.h:369
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2331
void SetOptStat(Int_t stat=1)
The type of information printed in the histogram statistics box can be selected via the parameter mod...
Definition TStyle.cxx:1589
virtual TString GetFromPipe(const char *command)
Execute command and return output in TString.
Definition TSystem.cxx:681
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:417
Base class for several text objects.
Definition TText.h:22
virtual TText * DrawText(Double_t x, Double_t y, const char *text)
Draw this text with new coordinates.
Definition TText.cxx:175
virtual void SetNDC(Bool_t isNDC=kTRUE)
Set NDC mode on if isNDC = kTRUE, off otherwise.
Definition TText.cxx:813
A TTree represents a columnar dataset.
Definition TTree.h:79
return c1
Definition legend1.C:41
return c2
Definition legend2.C:14
double T(double x)
Double_t Mean(Long64_t n, const T *a, const Double_t *w=0)
Return the weighted mean of an array a with length n.
Definition TMath.h:1073
Double_t RMS(Long64_t n, const T *a, const Double_t *w=0)
Return the Standard Deviation of an array a with length n.
Definition TMath.h:1167
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Definition TMathBase.h:362
Author
Rene Brun 7 July 2010

Definition in file memstatExample.C.