ROOT  6.06/09
Reference Guide
TMemStatShow.cxx
Go to the documentation of this file.
1 // @(#)root/treeviewer:$Id$
2 // Author: Rene Brun 21/09/2010
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2010, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TMemStatShow
13 Utility class post-processing the file generated by TMemStat (default memstat.root)
14 
15 TMemStat records all the calls to malloc and free and write a TTree
16 with the position where the memory is allocated/freed , as well as
17 the number of bytes.
18 
19 To use the class TMemStat, add the following statement at the beginning
20 of your script or program
21 ~~~ {.cpp}
22  TMemStat mm("gnubuiltin");
23 ~~~
24 or in an interactive session do something like:
25 ~~~ {.cpp}
26  root > TMemStat mm("gnubuiltin");
27  root > .x somescript.C
28  root > .q
29 ~~~
30 
31 another (may be more practical way) is to modify `$ROOTSYS/etc/system.rootrc`
32 and activate the variable
33 ~~~ {.cpp}
34  Root.TMemStat: 1
35 ~~~
36 The file collected by TMemStat is named memstat_ProcessID and can be analyzed and results shown
37 by executing the static function Show.
38 When TMemStat is active it recors every call to malloc/free in a ROOT Tree.
39 You must be careful when running jobs with many millions (or more) of calls
40 to malloc/free because the generated Tree may become very large.
41 The TMemStat constructor TMemStat(const char* system, Int_t buffersize, Int_t maxcalls)
42 has its 3 arguments optional:
43  - system refers to the internal algorithm to compute the back traces.
44  the recommended value is "gnubuiltin"
45  - buffersize is the number of calls to malloc or free that can be stored in one memory buffer.
46  when the buffer is full, the calls to malloc/free pointing to the same location
47  are eliminated and not written to the final Tree. The default value 100000
48  is such that between 50 and 90% of the calls are eliminated depending on the application.
49  You can set buffersize <=1 to keep every single call to malloc/free.
50  - maxcalls can set a limit for the maximum number of calls to be registered in the Tree.
51  The default value is 5000000.
52 The 3 arguments can be set in `$ROOTSYS/etc/system.rootrc`
53 ~~~ {.cpp}
54  Root.TMemStat.system gnubuiltin
55  Root.TMemStat.buffersize 100000
56  Root.TMemStat.maxcalls 5000000
57 ~~~
58 TMemStat::Show creates 3 canvases.
59  - In canvas1 it displays a dynamic histogram showing for pages (10 kbytes by default)
60  the percentage of the page used.
61  A summary pave shows the total memory still in use when the TMemStat object
62  goes out of scope and the average occupancy of the pages.
63  The average occupancy gives a good indication of the memory fragmentation.
64  When moving the mouse on this canvas, a tooltip shows the backtrace for the allocations
65  at the address at the mouse position.
66  - In canvas2 it displays the histogram of memory leaks in decreasing order.
67  when moving the mouse on this canvas, a tooltip shows the backtrace for the leak
68  in the bin below the mouse.
69  - In canvas3 it displays the histogram of the nbigleaks largest leaks (default is 20)
70  for each leak, the number of allocs and average alloc size is shown.
71 
72 Simply do:
73 ~~~ {.cpp}
74  root > TMemStat::Show()
75 ~~~
76 or specifying arguments
77 ~~~ {.cpp}
78  root > TMemStat::Show(0.1,20,"mydir/mymemstat.root");
79 ~~~
80 The first argument to Show is the percentage of the time of the original job
81 that produced the file after which the display is updated. By default update=0.1,
82 ie 10 time intervals will be shown.
83 The second argument is nbigleaks. if <=0 canvas2 and canvas3 are not shown
84 The third argument is the imput file name (result of TMemStat).
85 If this argument is omitted, Show will take the most recent file
86 generated by TMemStat.
87 
88 You can restrict the address range to be analyzed via TMemStatShow::SetAddressRange
89 You can restrict the entry range to be analyzed via TMemStatShow::SetEntryRange
90 */
91 
92 #include "TMemStatShow.h"
93 #include "TMath.h"
94 #include "TFile.h"
95 #include "TTree.h"
96 #include "TCanvas.h"
97 #include "TStyle.h"
98 #include "TH1.h"
99 #include "TPaveText.h"
100 #include "TPaveLabel.h"
101 #include "TSystem.h"
102 #include "TGClient.h"
103 #include "TGToolTip.h"
104 #include "TRootCanvas.h"
105 
106  TTree *TMemStatShow::fgT = 0; //TMemStat Tree
107  TH1D *TMemStatShow::fgHalloc = 0; //histogram with allocations
108  TH1D *TMemStatShow::fgHfree = 0; //histogram with frees
109  TH1D *TMemStatShow::fgH = 0; //histogram with allocations - frees
110  TH1I *TMemStatShow::fgHleaks = 0; //histogram with leaks
111  TH1I *TMemStatShow::fgHentry = 0; //histogram with entry numbers in the TObjArray
112  TH1I *TMemStatShow::fgHdiff = 0; //histogram with diff of entry number between alloc/free
113 
114  TGToolTip *TMemStatShow::fgTip1 = 0; //pointer to tool tip for canvas 1
115  TGToolTip *TMemStatShow::fgTip2 = 0; //pointer to tool tip for canvas 2
116  TObjArray *TMemStatShow::fgBtidlist = 0; //list of back trace ids
117  Double_t *TMemStatShow::fgV1 = 0; //pointer to V1 array of TTree::Draw (pos)
118  Double_t *TMemStatShow::fgV2 = 0; //pointer to V2 array of TTree::Draw (nbytes)
119  Double_t *TMemStatShow::fgV3 = 0; //pointer to V3 array of TTree::Draw (time)
120  Double_t *TMemStatShow::fgV4 = 0; //pointer to V4 array of TTree::Draw (btid)
121  TCanvas *TMemStatShow::fgC1 = 0; //pointer to canvas showing allocs/deallocs vs time
122  TCanvas *TMemStatShow::fgC2 = 0; //pointer to canvas with leaks in decreasing order
123  TCanvas *TMemStatShow::fgC3 = 0; //pointer to canvas showing the main leaks
124 
125  Long64_t TMemStatShow::fgEntryFirst = 0; //first address to process
126  Long64_t TMemStatShow::fgEntryN = 0; //number of addresses in bytes to process
127  Long64_t TMemStatShow::fgAddressFirst = 0; //first entry to process
128  Long64_t TMemStatShow::fgAddressN = 0; //number of entries to process
129 
130 ////////////////////////////////////////////////////////////////////////////////
131 /// Specify a memory address range to process (static function).
132 /// This function can be used to restrict the range of memory addresses
133 /// to be analyzed. For example whem TmemStat is run on a 64 bits machine and
134 /// the results visualized on a 32 bits machine, it might be necessary to
135 /// restrict the analysis range to the addresses below 2 Gigabytes, eg
136 /// TMemStatShow::SetMemoryRange(500000000,0); //analyse only the first 500 MBytes
137 /// - first : first address to process (default is 0)
138 /// - nbytes : number of addresses in bytes to process starting at first
139 /// if 0 (default), then all addresses are processed
140 
142 {
143  fgAddressFirst = first;
144  fgAddressN = nbytes;
145 }
146 
147 ////////////////////////////////////////////////////////////////////////////////
148 ///Specify a range of entries to process (static function)
149 /// - first : first entry to process (default is 0)
150 /// - nentries : number of entries to process starting at first
151 /// if 0 (default), then all entries are processed
152 /// call this function when the amount of data collected in the Tree is large
153 /// and therefore making the analysis slow.
154 
156 {
157  fgEntryFirst = first;
158  fgEntryN = nentries;
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 /// Function called by TMemStat::Show
163 /// Open the memstat data file, then call TTree::Draw to precompute
164 /// the arrays of positions and nbytes per entry.
165 /// update is the time interval in the data file in seconds after which
166 /// the display is updated. For example is the job producing the memstat.root file
167 /// took 100s to execute, an update of 0.1s will generate 1000 time views of
168 /// the memory use.
169 /// the histogram hbigleaks will contain the nbigleaks largest leaks
170 /// if fname=="*" (default), the most recent file memstat*.root will be taken.
171 
172 void TMemStatShow::Show(double update, int nbigleaks, const char* fname)
173 {
174 
175  TString s;
176  if (!fname || strlen(fname) <5 || strstr(fname,"*")) {
177  //take the most recent file memstat*.root
178  s = gSystem->GetFromPipe("ls -lrt memstat*.root");
179  Int_t ns = s.Length();
180  fname = strstr(s.Data()+ns-25,"memstat");
181  }
182  printf("Analyzing file: %s\n",fname);
183  TFile *f = TFile::Open(fname);
184  if (!f) {
185  printf("Cannot open file %s\n",fname);
186  return;
187  }
188  fgT = (TTree*)f->Get("T");
189  if (!fgT) {
190  printf("cannot find the TMemStat TTree named T in file %s\n",fname);
191  return;
192  }
193  if (update <= 0) {
194  printf("Illegal update value %g, changed to 0.01\n",update);
195  update = 0.01;
196  }
197  if (update < 0.001) printf("Warning update parameter is very small, processing may be slow\n");
198 
199  //autorestrict the amount of data to analyze
200  MemInfo_t minfo;
201  gSystem->GetMemInfo(&minfo);
202  Int_t nfree = minfo.fMemTotal - minfo.fMemUsed; //in Mbytes
203  printf("TMemStat::Show info: you are running on a machine with %d free MBytes of memory\n",nfree);
204  Long64_t nfreebytes = 200000*Long64_t(nfree); //use only 20% of the memory available
205  if (fgAddressN <=0) fgAddressN = nfreebytes;
207  if (fgEntryN > 0 && nentries > fgEntryN) nentries = fgEntryN;
208  if (2*8*nentries > 4*nfreebytes) {
209  nentries = 4*nfreebytes/16;
210  printf("not enough memory, restricting analysis to %lld entries\n",nentries);
211  }
212  fgT->SetEstimate(nentries);
213  Long64_t nsel = fgT->Draw("pos","pos>0","goff",nentries);
214  fgV1 = fgT->GetV1();
215  Long64_t ivmin = (Long64_t)TMath::MinElement(nsel,fgV1);
216  Long64_t ivmax = (Long64_t)TMath::MaxElement(nsel,fgV1);
217  if (ivmax-ivmin > fgAddressN) ivmax = ivmin+fgAddressN;
218  printf("TMemStatShow::Show will analyze only %lld bytes in its first pass\n",ivmax);
219 
220 
221  //initialize statics
222  fgTip1 = 0;
223  fgTip2 = 0;
224  fgBtidlist = 0;
225 
226  Long64_t ne = nfreebytes/32LL;
227  if (ne < nentries) nentries = ne;
228  fgT->SetEstimate(nentries+10);
229  printf("sel: ivmin=%lld, ivmax=%lld, nentries=%lld\n",ivmin,ivmax,nentries);
230  nsel = fgT->Draw("pos:nbytes:time:btid",
231  TString::Format("pos>%g && pos<%g",Double_t(ivmin),Double_t(ivmax)),
232  "goff",nentries,fgEntryFirst);
233 
234  //now we compute the best binning for the histogram
235  Int_t nbytes;
236  Double_t pos;
237  fgV1 = fgT->GetV1();
238  fgV2 = fgT->GetV2();
239  fgV3 = fgT->GetV3();
240  fgV4 = fgT->GetV4();
241  ivmin = (Long64_t)TMath::MinElement(nsel,fgV1);
242  ivmax = (Long64_t)TMath::MaxElement(nsel,fgV1);
243  Long64_t bw = 1000;
244  Double_t dvv = (Double_t(ivmax) - Double_t(ivmin))/Double_t(bw);
245  Long64_t nbins = Long64_t(dvv);
246  ivmin = ivmin -ivmin%bw;
247  ivmax = ivmin+bw*nbins;
248  Long64_t nvm = Long64_t(ivmax-ivmin+1);
249  printf("==>The data Tree contains %lld entries with addresses in range[%lld,%lld]\n",nsel,ivmin,ivmax);
250  //ne = (1000000*nfree-nvm*12)/32;
251  ne = 1000000LL*nfree/32LL;
252  if (ne < 0) return;
253  if (ne < nentries) {
254  //we take only the first side of the allocations
255  //we are mostly interested by the small allocations, so we select
256  //only values in the first gigabyte
257  nsel = fgT->Draw("pos:nbytes:time:btid",
258  TString::Format("pos>=%g && pos<%g",Double_t(ivmin),Double_t(ivmax)),"goff",ne,fgEntryFirst);
259  fgV1 = fgT->GetV1();
260  fgV2 = fgT->GetV2();
261  fgV3 = fgT->GetV3();
262  fgV4 = fgT->GetV4();
263  ivmin = (Long64_t)TMath::MinElement(nsel,fgV1);
264  ivmax = (Long64_t)TMath::MaxElement(nsel,fgV1);
265  bw = 10000;
266  dvv = (Double_t(ivmax) - Double_t(ivmin))/Double_t(bw);
267  nbins = Long64_t(dvv+0.5);
268  ivmin = ivmin -ivmin%bw;
269  ivmax = ivmin+bw*nbins;
270  printf("==>Address range or/and Entry range is too large\n");
271  printf("==>restricting the analysis range to [%lld,%lld] and %lld entries\n",ivmin,ivmax,ne);
272  printf("==>you can restrict the address range with TMemStatShow::SetAddressRange\n");
273  printf("==>you can restrict the entries range with TMemStatShow::SetEntryRange\n");
274  }
275  update *= 0.0001*fgV3[nsel-1]; //convert time per cent in seconds
276  nvm = Long64_t(ivmax-ivmin);
277  Long64_t *nbold = new Long64_t[nvm];
278  Int_t *ientry = new Int_t[nvm];
279  if (!nbold || !ientry) {
280  printf("you do not have enough memory to run, %lld bytes needed\n",12*nvm);
281  return;
282  }
283  memset(nbold,0,nvm*8);
284  memset(ientry,0,nvm*4);
285  Double_t dv = (ivmax-ivmin)/nbins;
286  TH1D *h = new TH1D("h",Form("%s;pos;per cent of pages used",fname),nbins,ivmin,ivmax);
287  fgH = h;
288  TAxis *axis = h->GetXaxis();
289  gStyle->SetOptStat("ie");
290  h->SetFillColor(kRed);
291  h->SetMinimum(0);
292  h->SetMaximum(100);
293  fgHalloc = new TH1D("fgHalloc",Form("%s;pos;number of mallocs",fname),nbins,ivmin,ivmax);
294  fgHfree = new TH1D("fgHfree", Form("%s;pos;number of frees",fname),nbins,ivmin,ivmax);
295  fgHdiff = new TH1I("fgHdiff","",1000,0,1e5);
296  //open a canvas and draw the empty histogram
297  fgC1 = new TCanvas("fgC1","c1",1200,600);
299  fgC1->SetGridx();
300  fgC1->SetGridy();
301  h->Draw();
302  //create a TPaveText to show the summary results
303  TPaveText *pvt = new TPaveText(.5,.9,.75,.99,"brNDC");
304  pvt->Draw();
305  //create a TPaveLabel to show the time
306  TPaveLabel *ptime = new TPaveLabel(.905,.7,.995,.76,"time","brNDC");
307  ptime->SetFillColor(kYellow-3);
308  ptime->Draw();
309  //draw producer identifier
310  TNamed *named = (TNamed*)fgT->GetUserInfo()->FindObject("SysInfo");
311  TText tmachine;
312  tmachine.SetTextSize(0.02);
313  tmachine.SetNDC();
314  if (named) tmachine.DrawText(0.01,0.01,named->GetTitle());
315 
316  //start loop on selected rows
317  Int_t bin,nb=0,j;
318  Long64_t ipos;
319  Double_t dbin,rest,time;
320  Double_t updateLast = 0;
321  Int_t nleaks = 0;
322  Int_t i;
323  for (i=0;i<nsel;i++) {
324  pos = fgV1[i];
325  ipos = (Long64_t)(pos-ivmin);
326  nbytes = (Int_t)fgV2[i];
327  time = 0.0001*fgV3[i];
328  bin = axis->FindBin(pos);
329  if (bin<1 || bin>nbins) continue;
330  dbin = axis->GetBinUpEdge(bin)-pos;
331  if (nbytes > 0) {
332  ientry[ipos] = i;
333  fgHalloc->Fill(pos);
334  if (dbin > nbytes) dbin = nbytes;
335  //fill bytes in the first page
336  h->AddBinContent(bin,100*dbin/dv);
337  //fill bytes in full following pages
338  nb = Int_t((nbytes-dbin)/dv);
339  if (bin+nb >nbins) nb = nbins-bin;
340  for (j=1;j<=nb;j++) h->AddBinContent(bin+j,100);
341  //fill the bytes remaining in last page
342  rest = nbytes-nb*dv-dbin;
343  if (rest > 0) h->AddBinContent(bin+nb+1,100*rest/dv);
344  //we save nbytes at pos. This info will be used when we free this slot
345  //if (nbold[ipos] > 0) printf("reallocating %d bytes (was %lld) at %lld, entry=%d\n",nbytes,nbold[ipos],ipos,i);
346  if (nbold[ipos] == 0) {
347  nleaks++;
348  //save the Tree entry number where we made this allocation
349  ientry[ipos] = i;
350  }
351  nbold[ipos] = nbytes;
352  } else {
353  fgHfree->Fill(pos);
354  nbytes = nbold[ipos];
355  if (bin+nb >nbins) nb = nbins-bin;
356  nbold[ipos] = 0; nleaks--;
357  fgHdiff->Fill(i-ientry[ipos]);
358  if (nbytes <= 0) continue;
359  //fill bytes free in the first page
360  if (dbin > nbytes) dbin = nbytes;
361  h->AddBinContent(bin,-100*dbin/dv);
362  //fill bytes free in full following pages
363  nb = Int_t((nbytes-dbin)/dv);
364  if (bin+nb >nbins) nb = nbins-bin;
365  for (j=1;j<=nb;j++) h->AddBinContent(bin+j,-100);
366  //fill the bytes free in in last page
367  rest = nbytes-nb*dv-dbin;
368  if (rest > 0) h->AddBinContent(bin+nb+1,-100*rest/dv);
369 
370  }
371  if (time -updateLast > update) {
372  //update canvas at regular intervals
373  updateLast = time;
374  h->SetEntries(i);
375  fgC1->Modified();
376  pvt->GetListOfLines()->Delete();
377  Double_t mbytes = 0;
378  Int_t nonEmpty = 0;
379  Double_t w;
380  for (Int_t k=1;k<nbins;k++) {
381  w = h->GetBinContent(k);
382  if (w > 0) {
383  nonEmpty++;
384  mbytes += 0.01*w*dv;
385  }
386  }
387  Double_t occupancy = mbytes/(nonEmpty*0.01*dv);
388  pvt->AddText(Form("memory used = %g Mbytes",mbytes*1e-6));
389  pvt->AddText(Form("page occupancy = %f per cent",occupancy));
390  pvt->AddText("(for non empty pages only)");
391  ptime->SetLabel(Form("%g sec",time));
392 
393  fgC1->Update();
395  }
396  }
397  h->SetEntries(nsel);
398  if (nleaks < 0) nleaks=0;
399  Int_t nlmax = nleaks;
400  nleaks += 1000;
401  Int_t *lindex = new Int_t[nleaks];
402  Int_t *entry = new Int_t[nleaks];
403  Int_t *ileaks = new Int_t[nleaks];
404 
405  nleaks =0;
406  for (Int_t ii=0;ii<nvm;ii++) {
407  if (nbold[ii] > 0) {
408  ileaks[nleaks] = (Int_t)nbold[ii];
409  entry[nleaks] = ientry[ii];
410  nleaks++;
411  if (nleaks > nlmax) break;
412  }
413  }
414  TMath::Sort(nleaks,ileaks,lindex);
415  fgHentry = new TH1I("fgHentry","leak entry index",nleaks,0,nleaks);
416  fgHleaks = new TH1I("fgHleaks","leaks;leak number;nbytes in leak",nleaks,0,nleaks);
417  for (Int_t k=0;k<nleaks;k++) {
418  Int_t kk = lindex[k];
419  i = entry[kk];
420  fgHentry->SetBinContent(k+1,i);
421  fgHleaks->SetBinContent(k+1,ileaks[kk]);
422  }
423  delete [] ileaks;
424  delete [] entry;
425  delete [] lindex;
426  delete [] nbold;
427  delete [] ientry;
428  fgHentry->SetEntries(nleaks);
429  fgHleaks->SetEntries(nleaks);
430 
431 
432  //construct the first tooltip
433  fgC1->Modified();
434  fgC1->Update();
436  TGMainFrame *frm1 = dynamic_cast<TGMainFrame *>(rc1);
437  // create the tooltip with a timeout of 250 ms
438  if (!fgTip1) fgTip1 = new TGToolTip(gClient->GetDefaultRoot(), frm1, "", 250);
439  fgC1->Connect("ProcessedEvent(Int_t, Int_t, Int_t, TObject*)",
440  "TMemStatShow", 0, "EventInfo1(Int_t, Int_t, Int_t, TObject*)");
441  if (nbigleaks <= 0) return;
442 
443  //---------------------------------------------------------------------------
444  //open a second canvas and draw the histogram with leaks in decreasing order
445  fgC2 = new TCanvas("fgC2","c2",1200,600);
447  fgC2->SetGridx();
448  fgC2->SetGridy();
449  fgC2->SetLogy();
451  if (nleaks > 1000) fgHleaks->GetXaxis()->SetRange(1,1000);
452  fgHleaks->Draw();
453  //draw producer identifier
454  if (named) tmachine.DrawText(0.01,0.01,named->GetTitle());
455 
456  //construct the second tooltip
458  TGMainFrame *frm2 = dynamic_cast<TGMainFrame *>(rc2);
459  // create the tooltip with a timeout of 250 ms
460  if (!fgTip2) fgTip2 = new TGToolTip(gClient->GetDefaultRoot(), frm2, "", 250);
461  fgC2->Connect("ProcessedEvent(Int_t, Int_t, Int_t, TObject*)",
462  "TMemStatShow", 0, "EventInfo2(Int_t, Int_t, Int_t, TObject*)");
463 
464  //---------------------------------------------------------------------------
465  //open a third canvas and draw the histogram with the nbigleaks largest leaks
466  fgC3 = new TCanvas("fgC3","c3",1200,600);
468  fgC3->SetGridx();
469  fgC3->SetGridy();
470  fgC3->SetLogx();
471  fgC3->SetLeftMargin(0.05);
472  fgC3->SetRightMargin(0.7);
473 
474  //fill histogram htotleaks accumulating in the same bin all leaks
475  //from btids having identical nchar first characters
476  TH1I *htotleaks = new TH1I("htotleaks","main leaks sorted by btids",100,0,0);
477  Int_t l;
478  for (l=1;l<=nleaks;l++) {
479  TString btstring = "";
480  TMemStatShow::FillBTString(l,1,btstring);
481  htotleaks->Fill(btstring.Data()+2,fgHleaks->GetBinContent(l));
482  }
483  Double_t tsize = 0.03;
484  if (nbigleaks > 30) tsize = 0.02;
485  htotleaks->LabelsOption(">");
486  htotleaks->GetXaxis()->SetRange(1,nbigleaks);
487  htotleaks->GetXaxis()->SetLabelSize(tsize);
488  htotleaks->GetYaxis()->SetLabelSize(tsize);
489  htotleaks->SetFillColor(kBlue-3);
490  htotleaks->Draw("hbar2 y+");
491 
492  //now loop on all the sorted bins and count the number of leaks
493  Double_t xr = 0.96*fgC3->GetLeftMargin();
494  Double_t xr2 = 1.04*fgC3->GetLeftMargin();
495  Double_t ytop = 1-fgC3->GetTopMargin();
496  Double_t ylow = fgC3->GetBottomMargin();
497  Double_t dy = (ytop-ylow)/nbigleaks;
498  TString btstring;
499  TText tnl;
500  tnl.SetNDC();
501  tnl.SetTextSize(tsize);
502  tnl.SetTextAlign(32);
503  TText tnl2;
504  tnl2.SetNDC();
505  tnl2.SetTextSize(tsize);
506  tnl2.SetTextAlign(12);
507  tnl2.SetTextColor(kYellow);
508  for (Int_t lb=1;lb<=nbigleaks;lb++) {
509  if (htotleaks->GetBinContent(lb) <= 0) continue;
510  const char *label = htotleaks->GetXaxis()->GetBinLabel(lb);
511  Int_t nchlabel = strlen(label);
512  if (nchlabel == 0) htotleaks->GetXaxis()->SetBinLabel(lb,"???");
513  Int_t nl =0;
514  for (l=1;l<=nleaks;l++) {
515  btstring = "";
516  TMemStatShow::FillBTString(l,1,btstring);
517  if (nchlabel > 0) {
518  if (!strncmp(btstring.Data()+2,label,nchlabel)) nl++;
519  } else {
520  if (btstring.Length() == 0) nl++;
521  }
522  }
523  Double_t yr = ylow +(lb-0.5)*dy;
524  tnl.DrawText(xr,yr,Form("%d",nl));
525  Int_t nbmean = Int_t(htotleaks->GetBinContent(lb)/nl);
526  if (lb == 1) tnl2.DrawText(xr2,yr,Form("%d bytes/alloc",nbmean));
527  else tnl2.DrawText(xr2,yr,Form("%d",nbmean));
528  }
529  tnl.DrawText(xr,ytop+0.015,"nallocs");
530  tnl.DrawText(1-fgC3->GetRightMargin(),0.5*ylow,"nbytes");
531  //draw producer identifier
532  if (named) tmachine.DrawText(0.01,0.01,named->GetTitle());
533 
534 }
535 
536 ////////////////////////////////////////////////////////////////////////////////
537 /// Static: draw the tooltip showing the backtrace for the allocatios histogram
538 
539 void TMemStatShow::EventInfo1(Int_t event, Int_t px, Int_t , TObject *selected)
540 {
541  if (!fgTip1) return;
542  fgTip1->Hide();
543  if (event == kMouseLeave)
544  return;
545  Double_t xpx = fgC1->AbsPixeltoX(px);
546  Double_t xpx1 = fgC1->AbsPixeltoX(px+1);
547  Int_t bin = fgH->GetXaxis()->FindBin(xpx);
548  Int_t bin1 = fgH->GetXaxis()->FindBin(xpx1);
549  //to take into account consecutive bins on the same pixel
550  while (bin <= bin1) {
551  if (fgH->GetBinContent(bin) > 0) break;
552  bin++;
553  }
554  if (fgH->GetBinContent(bin) <= 0) return;
555  if (bin <=0 || bin > fgH->GetXaxis()->GetNbins()) return;
556  Double_t posmin = fgH->GetXaxis()->GetBinLowEdge(bin);
557  Double_t posmax = fgH->GetXaxis()->GetBinUpEdge(bin);
558  Int_t nsel = (Int_t)fgT->GetSelectedRows();
559  Int_t entry = 0;
560  Int_t nhits = 0;
561  Int_t nbytes = 0;
562  //search for all allocations in this bin and select last one only
563  for (Int_t i=0;i<nsel;i++) {
564  if (fgV2[i] < 0) continue;
565  if (fgV1[i] < posmax && fgV1[i]+fgV2[i] >posmin) {
566  entry = i;
567  nbytes = (Int_t)fgV2[i];
568  nhits++;
569  }
570  }
571  if (!nhits) return;
572 
573  Double_t time = 0.0001*fgV3[entry];
574  TString ttip;
575  TMemStatShow::FillBTString(entry,0,ttip);
576 
577  if (selected) {
578  TString form1 = TString::Format(" Alloc(%d) at %lld of %d bytes, time=%gseconds\n\n",nhits,Long64_t(fgV1[entry]),nbytes,time);
579  fgTip1->SetText(TString::Format("%s%s",form1.Data(),ttip.Data() ));
580  fgTip1->SetPosition(px+15, 100);
581  fgTip1->Reset();
582  }
583 }
584 
585 ////////////////////////////////////////////////////////////////////////////////
586 /// Static: draw the tooltip showing the backtrace for the histogram of leaks
587 
588 void TMemStatShow::EventInfo2(Int_t event, Int_t px, Int_t , TObject *selected)
589 {
590  if (!fgTip2) return;
591  fgTip2->Hide();
592  if (event == kMouseLeave)
593  return;
594  Double_t xpx = fgC2->AbsPixeltoX(px);
595  Int_t bin = fgHleaks->GetXaxis()->FindBin(xpx);
596  if (bin <=0 || bin > fgHleaks->GetXaxis()->GetNbins()) return;
597  Int_t nbytes = (Int_t)fgHleaks->GetBinContent(bin);
599  Double_t time = 0.0001*fgV3[entry];
600  TString ttip;
601  TMemStatShow::FillBTString(entry,0,ttip);
602 
603  if (selected) {
604  TString form1 = TString::Format(" Leak number=%d, leaking %d bytes at entry=%d time=%gseconds\n\n",bin,nbytes,entry,time);
605  fgTip2->SetText(TString::Format("%s%s",form1.Data(),ttip.Data() ));
606  fgTip2->SetPosition(px+15, 100);
607  fgTip2->Reset();
608  }
609 }
610 
611 ////////////////////////////////////////////////////////////////////////////////
612 /// Static: fill btstring with the traceback corresponding to entry in T
613 /// btstring must be initialized in calling function
614 
616 {
617  Int_t btid = (Int_t)fgV4[entry];
618  TH1I *hbtids = (TH1I*)fgT->GetUserInfo()->FindObject("btids");
619  if (!hbtids) return;
620  if (!fgBtidlist) fgBtidlist = (TObjArray*)fgT->GetUserInfo()->FindObject("FAddrsList");
621  if (!fgBtidlist) fgBtidlist = (TObjArray*)gFile->Get("FAddrsList"); //old memstat files
622  if (!fgBtidlist) return;
623  Int_t nbt = (Int_t)hbtids->GetBinContent(btid-1);
624  for (Int_t i=0;i<nbt;i++) {
625  Int_t j = (Int_t)hbtids->GetBinContent(btid+i);
626  TNamed *nm = (TNamed*)fgBtidlist->At(j);
627  if (nm==0) break;
628  char *title = (char*)nm->GetTitle();
629  Int_t nch = strlen(title);
630  if (nch < 10) continue;
631  if (strstr(title,"malloc")) continue;
632  if (strstr(title,"memstat")) continue;
633  if (strstr(title,"TMemStatHook")) continue;
634  char *bar = strchr(title+5,'|');
635  if (!bar) bar = title;
636 
637  if (strstr(bar,"operator new")) continue;
638  if (strstr(bar,"libMemStat")) continue;
639  if (strstr(bar,"G__Exception")) continue;
640  if (mode) {
641  btstring += TString::Format("%s ",bar);
642  if (btstring.Length() > 80) return;
643  } else {
644  btstring += TString::Format("%2d %s\n",i,bar+1);
645  }
646  }
647 }
virtual Double_t * GetV3()
Definition: TTree.h:454
static void FillBTString(Int_t bin, Int_t mode, TString &btstring)
Static: fill btstring with the traceback corresponding to entry in T btstring must be initialized in ...
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
virtual void SetGridx(Int_t value=1)
Definition: TPad.h:327
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3159
static Double_t * fgV1
Definition: TMemStatShow.h:50
An array of TObjects.
Definition: TObjArray.h:39
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:420
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:404
static Long64_t fgEntryN
Definition: TMemStatShow.h:61
virtual void Draw(Option_t *option="")
Draw this pavetext with its current attributes.
Definition: TPaveText.cxx:211
static void Show(Double_t update=0.1, Int_t nbigleaks=20, const char *fname="*")
Function called by TMemStat::Show Open the memstat data file, then call TTree::Draw to precompute the...
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4629
long long Long64_t
Definition: RtypesCore.h:69
static TObjArray * fgBtidlist
Definition: TMemStatShow.h:49
virtual void SetMaximum(Double_t maximum=-1111)
Definition: TH1.h:394
virtual void LabelsOption(Option_t *option="h", Option_t *axis="X")
Set option(s) to draw axis with labels.
Definition: TH1.cxx:4901
Ssiz_t Length() const
Definition: TString.h:390
virtual Double_t * GetV4()
Definition: TTree.h:456
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition: TAxis.cxx:411
Definition: Rtypes.h:61
void Reset()
Reset tool tip popup delay timer.
Definition: TGToolTip.cxx:259
R__EXTERN TStyle * gStyle
Definition: TStyle.h:423
static TH1D * fgH
Definition: TMemStatShow.h:42
void SetText(const char *new_text)
Set new tool tip text.
Definition: TGToolTip.cxx:386
TH1 * h
Definition: legend2.C:5
virtual TString GetFromPipe(const char *command)
Execute command and return output in TString.
Definition: TSystem.cxx:684
static TGToolTip * fgTip2
Definition: TMemStatShow.h:48
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
Definition: TPaveText.cxx:160
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:489
virtual void SetMinimum(Double_t minimum=-1111)
Definition: TH1.h:395
THist< 1, int > TH1I
Definition: THist.h:317
static TCanvas * fgC3
Definition: TMemStatShow.h:56
Basic string class.
Definition: TString.h:137
#define gClient
Definition: TGClient.h:174
int Int_t
Definition: RtypesCore.h:41
virtual TList * GetListOfLines() const
Definition: TPaveText.h:63
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:496
void Hide()
Hide tool tip window.
Definition: TGToolTip.cxx:246
int nbins[3]
Definition: Rtypes.h:61
static void SetEntryRange(Long64_t nentries=0, Long64_t first=0)
Specify a range of entries to process (static function)
static Long64_t fgAddressN
Definition: TMemStatShow.h:59
THist< 1, double > TH1D
Definition: THist.h:314
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3851
static Double_t * fgV3
Definition: TMemStatShow.h:52
const char * Data() const
Definition: TString.h:349
Float_t GetTopMargin() const
Definition: TAttPad.h:56
static TCanvas * fgC2
Definition: TMemStatShow.h:55
Float_t GetRightMargin() const
Definition: TAttPad.h:55
Float_t GetBottomMargin() const
Definition: TAttPad.h:53
virtual Long64_t GetSelectedRows()
Definition: TTree.h:428
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:2334
static TH1I * fgHentry
Definition: TMemStatShow.h:44
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
virtual void AddBinContent(Int_t bin)
Increment bin content by 1.
Definition: TH1.h:625
static TCanvas * fgC1
Definition: TMemStatShow.h:54
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Definition: TMath.h:1002
Base class for several text objects.
Definition: TText.h:42
virtual void SetNDC(Bool_t isNDC=kTRUE)
Set NDC mode on if isNDC = kTRUE, off otherwise.
Definition: TText.cxx:809
virtual void SetLogx(Int_t value=1)
Set Lin/Log scale for X.
Definition: TPad.cxx:5305
void SetPosition(Int_t x, Int_t y)
Set popup position within specified frame (as specified in the ctor).
Definition: TGToolTip.cxx:405
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:5692
virtual void SetTextAlign(Short_t align=11)
Definition: TAttText.h:55
virtual void SetLabel(const char *label)
Definition: TPaveLabel.h:53
A Pave (see TPave) with a text centered in the Pave.
Definition: TPaveLabel.h:32
static Long64_t fgEntryFirst
Definition: TMemStatShow.h:60
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
Non-static method is used to connect from the signal of this object to the receiver slot...
Definition: TQObject.cxx:1135
static TH1I * fgHdiff
Definition: TMemStatShow.h:45
static void EventInfo2(Int_t event, Int_t px, Int_t py, TObject *selected)
Static: draw the tooltip showing the backtrace for the histogram of leaks.
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis from bin first to last.
Definition: TAxis.cxx:831
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8236
Class to manage histogram axis.
Definition: TAxis.h:36
static TH1D * fgHalloc
Definition: TMemStatShow.h:40
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition: TH1.cxx:2878
virtual void SetFillColor(Color_t fcolor)
Definition: TAttFill.h:50
Int_t GetNbins() const
Definition: TAxis.h:125
virtual Double_t * GetV2()
Definition: TTree.h:452
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:499
1-D histogram with a int per channel (see TH1 documentation)}
Definition: TH1.h:529
static TH1I * fgHleaks
Definition: TMemStatShow.h:43
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:8543
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
static Double_t * fgV4
Definition: TMemStatShow.h:53
char * Form(const char *fmt,...)
TLine * l
Definition: textangle.C:4
static TH1D * fgHfree
Definition: TMemStatShow.h:41
TAxis * GetYaxis()
Definition: TH1.h:320
1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:613
Long64_t entry
virtual void SetLabelSize(Float_t size=0.04)
Set size of axis labels The size is expressed in per cent of the pad width.
Definition: TAttAxis.cxx:186
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:264
Float_t GetLeftMargin() const
Definition: TAttPad.h:54
The Canvas class.
Definition: TCanvas.h:48
TCanvasImp * GetCanvasImp() const
Get canvas implementation pointer if any.
Definition: TCanvas.h:181
static TTree * fgT
Definition: TMemStatShow.h:39
A Pave (see TPave) with text, lines or/and boxes inside.
Definition: TPaveText.h:35
virtual void Draw(Option_t *option="")
Draw this pavelabel with its current attributes.
Definition: TPaveLabel.cxx:77
double f(double x)
double Double_t
Definition: RtypesCore.h:55
virtual void SetGridy(Int_t value=1)
Definition: TPad.h:328
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
static void SetAddressRange(Long64_t nbytes=0, Long64_t first=0)
Specify a memory address range to process (static function).
static Double_t * fgV2
Definition: TMemStatShow.h:51
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:356
int nentries
Definition: THbookFile.cxx:89
T MaxElement(Long64_t n, const T *a)
Definition: TMath.h:688
virtual void SetBinLabel(Int_t bin, const char *label)
Set label for bin.
Definition: TAxis.cxx:793
static Long64_t fgAddressFirst
Definition: TMemStatShow.h:58
static void EventInfo1(Int_t event, Int_t px, Int_t py, TObject *selected)
Static: draw the tooltip showing the backtrace for the allocatios histogram.
Definition: Rtypes.h:61
Int_t fMemTotal
Definition: TSystem.h:191
virtual void SetRightMargin(Float_t rightmargin)
Set Pad right margin in fraction of the pad width.
Definition: TAttPad.cxx:117
Mother of all ROOT objects.
Definition: TObject.h:58
Int_t fMemUsed
Definition: TSystem.h:192
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:1252
virtual TText * DrawText(Double_t x, Double_t y, const char *text)
Draw this text with new coordinates.
Definition: TText.cxx:171
Double_t AbsPixeltoX(Int_t px)
Definition: TPad.h:171
virtual void SetTextColor(Color_t tcolor=1)
Definition: TAttText.h:57
virtual void SetEntries(Double_t n)
Definition: TH1.h:382
virtual Long64_t GetEntries() const
Definition: TTree.h:382
A TTree object has a header with a name and a title.
Definition: TTree.h:94
Definition: Rtypes.h:61
void SetFrameFillColor(Color_t color=1)
Definition: TAttPad.h:83
virtual int GetMemInfo(MemInfo_t *info) const
Returns ram and swap memory usage info into the MemInfo_t structure.
Definition: TSystem.cxx:2433
virtual void SetTextSize(Float_t tsize=1)
Definition: TAttText.h:60
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
virtual void Update()
Update canvas pad buffers.
Definition: TCanvas.cxx:2179
virtual Double_t * GetV1()
Definition: TTree.h:450
static TGToolTip * fgTip1
Definition: TMemStatShow.h:47
void Modified(Bool_t flag=1)
Definition: TPad.h:407
TAxis * GetXaxis()
Definition: TH1.h:319
virtual void SetLeftMargin(Float_t leftmargin)
Set Pad left margin in fraction of the pad width.
Definition: TAttPad.cxx:107
T MinElement(Long64_t n, const T *a)
Definition: TMath.h:681
#define gFile
Definition: TFile.h:307
virtual void SetLogy(Int_t value=1)
Set Lin/Log scale for Y.
Definition: TPad.cxx:5318