Logo ROOT  
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 {
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 {
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  }
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();
450  fgHleaks->SetFillColor(kRed-3);
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);
598  Int_t entry = (Int_t)fgHentry->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 
615 void TMemStatShow::FillBTString(Int_t entry,Int_t mode,TString &btstring)
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 }
TAxis::GetBinLabel
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition: TAxis.cxx:440
TCanvas::GetCanvasImp
TCanvasImp * GetCanvasImp() const
Get canvas implementation pointer if any.
Definition: TCanvas.h:156
l
auto * l
Definition: textangle.C:4
kMouseLeave
@ kMouseLeave
Definition: Buttons.h:29
TH1::LabelsOption
virtual void LabelsOption(Option_t *option="h", Option_t *axis="X")
Set option(s) to draw axis with labels.
Definition: TH1.cxx:5221
TMath::MaxElement
T MaxElement(Long64_t n, const T *a)
Return maximum of array a of length n.
Definition: TMath.h:959
TMemStatShow::SetAddressRange
static void SetAddressRange(Long64_t nbytes=0, Long64_t first=0)
Specify a memory address range to process (static function).
Definition: TMemStatShow.cxx:141
TText::DrawText
virtual TText * DrawText(Double_t x, Double_t y, const char *text)
Draw this text with new coordinates.
Definition: TText.cxx:175
TAxis
Class to manage histogram axis.
Definition: TAxis.h:30
first
Definition: first.py:1
TMemStatShow::fgHalloc
static TH1D * fgHalloc
Definition: TMemStatShow.h:36
TTree::GetV4
virtual Double_t * GetV4()
Definition: TTree.h:537
e
#define e(i)
Definition: RSha256.hxx:121
TGMainFrame
Definition: TGFrame.h:444
TAxis::GetBinLowEdge
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:518
TObjArray
Definition: TObjArray.h:37
f
#define f(i)
Definition: RSha256.hxx:122
TTree::GetV1
virtual Double_t * GetV1()
Definition: TTree.h:531
TMemStatShow::fgTip1
static TGToolTip * fgTip1
Definition: TMemStatShow.h:43
TMemStatShow::EventInfo2
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.
Definition: TMemStatShow.cxx:588
TGToolTip::SetPosition
void SetPosition(Int_t x, Int_t y)
Set popup position within specified frame (as specified in the ctor).
Definition: TGToolTip.cxx:406
TH1I
1-D histogram with an int per channel (see TH1 documentation)}
Definition: TH1.h:531
TList::FindObject
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:577
TList::Delete
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:469
TString::Data
const char * Data() const
Definition: TString.h:369
TRootCanvas.h
Form
char * Form(const char *fmt,...)
TNamed::GetTitle
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:54
TMemStatShow::EventInfo1
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: TMemStatShow.cxx:539
TMemStatShow::fgTip2
static TGToolTip * fgTip2
Definition: TMemStatShow.h:44
Long64_t
long long Long64_t
Definition: RtypesCore.h:73
TTree
Definition: TTree.h:79
gFile
#define gFile
Definition: TFile.h:343
TAttPad::GetBottomMargin
Float_t GetBottomMargin() const
Definition: TAttPad.h:49
TH1D
1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:615
TMemStatShow::fgEntryN
static Long64_t fgEntryN
Definition: TMemStatShow.h:57
TStyle.h
TGeant4Unit::s
static constexpr double s
Definition: TGeant4SystemOfUnits.h:168
TFile::Open
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:3946
Int_t
int Int_t
Definition: RtypesCore.h:45
TAxis::GetBinUpEdge
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:528
TH1::SetBinContent
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:8677
TGToolTip::SetText
void SetText(const char *new_text)
Set new tool tip text.
Definition: TGToolTip.cxx:387
TString::Length
Ssiz_t Length() const
Definition: TString.h:410
TMemStatShow::fgC1
static TCanvas * fgC1
Definition: TMemStatShow.h:50
TSystem::GetFromPipe
virtual TString GetFromPipe(const char *command)
Execute command and return output in TString.
Definition: TSystem.cxx:681
TPad::SetGridy
virtual void SetGridy(Int_t value=1)
Definition: TPad.h:329
TGToolTip
Definition: TGToolTip.h:35
nentries
int nentries
Definition: THbookFile.cxx:91
TMemStatShow::fgHdiff
static TH1I * fgHdiff
Definition: TMemStatShow.h:41
TMemStatShow::FillBTString
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 ...
Definition: TMemStatShow.cxx:615
TMemStatShow::fgH
static TH1D * fgH
Definition: TMemStatShow.h:38
TTree::GetUserInfo
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:6249
TAttPad::GetTopMargin
Float_t GetTopMargin() const
Definition: TAttPad.h:52
TMath::Sort
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Definition: TMathBase.h:362
TAttPad::SetFrameFillColor
void SetFrameFillColor(Color_t color=1)
Definition: TAttPad.h:79
TObjArray::At
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
TString::Format
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:2311
TCanvas.h
TTree.h
TString
Definition: TString.h:136
TGeant4Unit::bar
static constexpr double bar
Definition: TGeant4SystemOfUnits.h:227
TMemStatShow::SetEntryRange
static void SetEntryRange(Long64_t nentries=0, Long64_t first=0)
Specify a range of entries to process (static function)
Definition: TMemStatShow.cxx:155
TMemStatShow::fgC3
static TCanvas * fgC3
Definition: TMemStatShow.h:52
TFile.h
TPaveLabel::Draw
virtual void Draw(Option_t *option="")
Draw this pavelabel with its current attributes.
Definition: TPaveLabel.cxx:77
TPaveLabel.h
TTree::SetEstimate
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8925
TPaveText.h
TTree::GetSelectedRows
virtual Long64_t GetSelectedRows()
Definition: TTree.h:508
TRootCanvas
Definition: TRootCanvas.h:42
TPad::Modified
void Modified(Bool_t flag=1)
Definition: TPad.h:414
gClient
#define gClient
Definition: TGClient.h:166
TPaveText::Draw
virtual void Draw(Option_t *option="")
Draw this pavetext with its current attributes.
Definition: TPaveText.cxx:234
TPad::AbsPixeltoX
Double_t AbsPixeltoX(Int_t px)
Definition: TPad.h:164
update
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
Definition: RooAdaptiveGaussKronrodIntegrator1D.cxx:652
TMemStatShow::Show
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...
Definition: TMemStatShow.cxx:172
TGToolTip::Reset
void Reset()
Reset tool tip popup delay timer.
Definition: TGToolTip.cxx:260
TAttAxis::SetLabelSize
virtual void SetLabelSize(Float_t size=0.04)
Set size of axis labels.
Definition: TAttAxis.cxx:203
TMemStatShow::fgV4
static Double_t * fgV4
Definition: TMemStatShow.h:49
kCyan
@ kCyan
Definition: Rtypes.h:66
TPad::SetLogy
virtual void SetLogy(Int_t value=1)
Set Lin/Log scale for Y.
Definition: TPad.cxx:5905
TAxis::SetRange
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
TText::SetNDC
virtual void SetNDC(Bool_t isNDC=kTRUE)
Set NDC mode on if isNDC = kTRUE, off otherwise.
Definition: TText.cxx:813
TPad::SetGridx
virtual void SetGridx(Int_t value=1)
Definition: TPad.h:328
TH1::GetBinContent
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4906
gStyle
R__EXTERN TStyle * gStyle
Definition: TStyle.h:412
TSystem.h
TH1::GetYaxis
TAxis * GetYaxis()
Definition: TH1.h:318
TTree::GetV2
virtual Double_t * GetV2()
Definition: TTree.h:533
TMemStatShow::fgHentry
static TH1I * fgHentry
Definition: TMemStatShow.h:40
h
#define h(i)
Definition: RSha256.hxx:124
TH1::SetEntries
virtual void SetEntries(Double_t n)
Definition: TH1.h:382
TNamed
Definition: TNamed.h:29
TMath::MinElement
T MinElement(Long64_t n, const T *a)
Return minimum of array a of length n.
Definition: TMath.h:952
MemInfo_t
Definition: TSystem.h:179
TGeant4Unit::ns
static constexpr double ns
Definition: TGeant4SystemOfUnits.h:167
TH1::Fill
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3274
TTree::Draw
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:427
TMemStatShow::fgEntryFirst
static Long64_t fgEntryFirst
Definition: TMemStatShow.h:56
TPaveLabel::SetLabel
virtual void SetLabel(const char *label)
Definition: TPaveLabel.h:47
TAttPad::GetLeftMargin
Float_t GetLeftMargin() const
Definition: TAttPad.h:50
TGClient.h
kRed
@ kRed
Definition: Rtypes.h:66
TStyle::SetOptStat
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:1592
TFile
Definition: TFile.h:54
TPaveText::AddText
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:183
gSystem
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
TPaveLabel
Definition: TPaveLabel.h:20
TAttPad::SetLeftMargin
virtual void SetLeftMargin(Float_t leftmargin)
Set Pad left margin in fraction of the pad width.
Definition: TAttPad.cxx:109
TMemStatShow::fgC2
static TCanvas * fgC2
Definition: TMemStatShow.h:51
TAxis::SetBinLabel
virtual void SetBinLabel(Int_t bin, const char *label)
Set label for bin.
Definition: TAxis.cxx:823
TMemStatShow::fgAddressFirst
static Long64_t fgAddressFirst
Definition: TMemStatShow.h:54
TAttPad::GetRightMargin
Float_t GetRightMargin() const
Definition: TAttPad.h:51
TText
Definition: TText.h:22
TMemStatShow::fgBtidlist
static TObjArray * fgBtidlist
Definition: TMemStatShow.h:45
Double_t
double Double_t
Definition: RtypesCore.h:59
TQObject::Connect
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:864
TAttPad::SetRightMargin
virtual void SetRightMargin(Float_t rightmargin)
Set Pad right margin in fraction of the pad width.
Definition: TAttPad.cxx:119
TCanvas
Definition: TCanvas.h:23
TObject
Definition: TObject.h:37
TGToolTip.h
TPaveText::GetListOfLines
virtual TList * GetListOfLines() const
Definition: TPaveText.h:49
TMemStatShow::fgV1
static Double_t * fgV1
Definition: TMemStatShow.h:46
TMemStatShow::fgV3
static Double_t * fgV3
Definition: TMemStatShow.h:48
TCanvas::Update
virtual void Update()
Update canvas pad buffers.
Definition: TCanvas.cxx:2500
TMemStatShow::fgAddressN
static Long64_t fgAddressN
Definition: TMemStatShow.h:55
TAxis::FindBin
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:293
kBlue
@ kBlue
Definition: Rtypes.h:66
TMemStatShow::fgHleaks
static TH1I * fgHleaks
Definition: TMemStatShow.h:39
TPaveText
Definition: TPaveText.h:21
MemInfo_t::fMemTotal
Int_t fMemTotal
Definition: TSystem.h:180
TMemStatShow::fgV2
static Double_t * fgV2
Definition: TMemStatShow.h:47
MemInfo_t::fMemUsed
Int_t fMemUsed
Definition: TSystem.h:181
TGeant4Unit::nm
static constexpr double nm
Definition: TGeant4SystemOfUnits.h:111
TPad::SetLogx
virtual void SetLogx(Int_t value=1)
Set Lin/Log scale for X.
Definition: TPad.cxx:5891
TH1::GetXaxis
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition: TH1.h:317
TMemStatShow::fgHfree
static TH1D * fgHfree
Definition: TMemStatShow.h:37
TGToolTip::Hide
void Hide()
Hide tool tip window.
Definition: TGToolTip.cxx:247
kYellow
@ kYellow
Definition: Rtypes.h:66
TH1.h
TMemStatShow::fgT
static TTree * fgT
Definition: TMemStatShow.h:35
TTree::GetEntries
virtual Long64_t GetEntries() const
Definition: TTree.h:458
TSystem::GetMemInfo
virtual int GetMemInfo(MemInfo_t *info) const
Returns ram and swap memory usage info into the MemInfo_t structure.
Definition: TSystem.cxx:2517
TSystem::ProcessEvents
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:417
TTree::GetV3
virtual Double_t * GetV3()
Definition: TTree.h:535
TAxis::GetNbins
Int_t GetNbins() const
Definition: TAxis.h:121
TMath.h
int
TH1::Draw
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition: TH1.cxx:2997
TMemStatShow.h