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
13Utility class post-processing the file generated by TMemStat (default memstat.root)
14
15TMemStat records all the calls to malloc and free and write a TTree
16with the position where the memory is allocated/freed , as well as
17the number of bytes.
18
19To use the class TMemStat, add the following statement at the beginning
20of your script or program
21~~~ {.cpp}
22 TMemStat mm("gnubuiltin");
23~~~
24or in an interactive session do something like:
25~~~ {.cpp}
26 root > TMemStat mm("gnubuiltin");
27 root > .x somescript.C
28 root > .q
29~~~
30
31another (may be more practical way) is to modify `$ROOTSYS/etc/system.rootrc`
32and activate the variable
33~~~ {.cpp}
34 Root.TMemStat: 1
35~~~
36The file collected by TMemStat is named memstat_ProcessID and can be analyzed and results shown
37by executing the static function Show.
38When TMemStat is active it recors every call to malloc/free in a ROOT Tree.
39You must be careful when running jobs with many millions (or more) of calls
40to malloc/free because the generated Tree may become very large.
41The TMemStat constructor TMemStat(const char* system, Int_t buffersize, Int_t maxcalls)
42has 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.
52The 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~~~
58TMemStat::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
72Simply do:
73~~~ {.cpp}
74 root > TMemStat::Show()
75~~~
76or specifying arguments
77~~~ {.cpp}
78 root > TMemStat::Show(0.1,20,"mydir/mymemstat.root");
79~~~
80The first argument to Show is the percentage of the time of the original job
81that produced the file after which the display is updated. By default update=0.1,
82ie 10 time intervals will be shown.
83The second argument is nbigleaks. if <=0 canvas2 and canvas3 are not shown
84The third argument is the imput file name (result of TMemStat).
85If this argument is omitted, Show will take the most recent file
86generated by TMemStat.
87
88You can restrict the address range to be analyzed via TMemStatShow::SetAddressRange
89You 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{
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
172void 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;
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();
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;
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
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
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
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}
@ 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:41
double Double_t
Definition: RtypesCore.h:55
long long Long64_t
Definition: RtypesCore.h:69
@ kRed
Definition: Rtypes.h:64
@ kCyan
Definition: Rtypes.h:64
@ kBlue
Definition: Rtypes.h:64
@ kYellow
Definition: Rtypes.h:64
#define gFile
Definition: TFile.h:338
#define gClient
Definition: TGClient.h:166
int nentries
Definition: THbookFile.cxx:89
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:407
R__EXTERN TSystem * gSystem
Definition: TSystem.h:560
virtual void SetLabelSize(Float_t size=0.04)
Set size of axis labels.
Definition: TAttAxis.cxx:204
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
void SetFrameFillColor(Color_t color=1)
Definition: TAttPad.h:73
virtual void SetLeftMargin(Float_t leftmargin)
Set Pad left margin in fraction of the pad width.
Definition: TAttPad.cxx:110
Float_t GetLeftMargin() const
Definition: TAttPad.h:44
Float_t GetBottomMargin() const
Definition: TAttPad.h:43
virtual void SetRightMargin(Float_t rightmargin)
Set Pad right margin in fraction of the pad width.
Definition: TAttPad.cxx:120
Float_t GetRightMargin() const
Definition: TAttPad.h:45
Float_t GetTopMargin() const
Definition: TAttPad.h:46
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition: TAttText.h:41
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition: TAttText.h:43
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 void SetBinLabel(Int_t bin, const char *label)
Set label for bin.
Definition: TAxis.cxx:809
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition: TAxis.cxx:426
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:279
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:504
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 from bin first to last.
Definition: TAxis.cxx:903
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:514
The Canvas class.
Definition: TCanvas.h:31
TCanvasImp * GetCanvasImp() const
Get canvas implementation pointer if any.
Definition: TCanvas.h:164
virtual void Update()
Update canvas pad buffers.
Definition: TCanvas.cxx:2339
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
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:3923
void Hide()
Hide tool tip window.
Definition: TGToolTip.cxx:246
void SetPosition(Int_t x, Int_t y)
Set popup position within specified frame (as specified in the ctor).
Definition: TGToolTip.cxx:405
void SetText(const char *new_text)
Set new tool tip text.
Definition: TGToolTip.cxx:386
void Reset()
Reset tool tip popup delay timer.
Definition: TGToolTip.cxx:259
1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:614
1-D histogram with an int per channel (see TH1 documentation)}
Definition: TH1.h:530
virtual void LabelsOption(Option_t *option="h", Option_t *axis="X")
Set option(s) to draw axis with labels.
Definition: TH1.cxx:5214
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition: TH1.h:316
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3275
TAxis * GetYaxis()
Definition: TH1.h:317
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:8666
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition: TH1.cxx:2998
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4899
virtual void SetEntries(Double_t n)
Definition: TH1.h:381
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:575
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
static TCanvas * fgC3
Definition: TMemStatShow.h:52
static TCanvas * fgC2
Definition: TMemStatShow.h:51
static TH1D * fgHalloc
Definition: TMemStatShow.h:36
static TCanvas * fgC1
Definition: TMemStatShow.h:50
static TH1I * fgHdiff
Definition: TMemStatShow.h:41
static TH1I * fgHentry
Definition: TMemStatShow.h:40
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 ...
static TTree * fgT
Definition: TMemStatShow.h:35
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.
static TH1D * fgHfree
Definition: TMemStatShow.h:37
static TGToolTip * fgTip2
Definition: TMemStatShow.h:44
static Double_t * fgV4
Definition: TMemStatShow.h:49
static Double_t * fgV1
Definition: TMemStatShow.h:46
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.
static TH1I * fgHleaks
Definition: TMemStatShow.h:39
static Double_t * fgV3
Definition: TMemStatShow.h:48
static Long64_t fgAddressN
Definition: TMemStatShow.h:55
static TObjArray * fgBtidlist
Definition: TMemStatShow.h:45
static void SetEntryRange(Long64_t nentries=0, Long64_t first=0)
Specify a range of entries to process (static function)
static Long64_t fgEntryFirst
Definition: TMemStatShow.h:56
static Double_t * fgV2
Definition: TMemStatShow.h:47
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...
static TH1D * fgH
Definition: TMemStatShow.h:38
static TGToolTip * fgTip1
Definition: TMemStatShow.h:43
static Long64_t fgEntryN
Definition: TMemStatShow.h:57
static Long64_t fgAddressFirst
Definition: TMemStatShow.h:54
static void SetAddressRange(Long64_t nbytes=0, Long64_t first=0)
Specify a memory address range to process (static function).
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
virtual void SetLogy(Int_t value=1)
Set Lin/Log scale for Y.
Definition: TPad.cxx:5864
virtual void SetGridx(Int_t value=1)
Definition: TPad.h:331
virtual void SetGridy(Int_t value=1)
Definition: TPad.h:332
virtual void SetLogx(Int_t value=1)
Set Lin/Log scale for X.
Definition: TPad.cxx:5850
void Modified(Bool_t flag=1)
Definition: TPad.h:417
Double_t AbsPixeltoX(Int_t px)
Definition: TPad.h:167
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.
Definition: TPaveLabel.cxx:77
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.
Definition: TPaveText.cxx:182
virtual void Draw(Option_t *option="")
Draw this pavetext with its current attributes.
Definition: TPaveText.cxx:233
virtual TList * GetListOfLines() const
Definition: TPaveText.h:49
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:867
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
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
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:1450
virtual int GetMemInfo(MemInfo_t *info) const
Returns ram and swap memory usage info into the MemInfo_t structure.
Definition: TSystem.cxx:2524
virtual TString GetFromPipe(const char *command)
Execute command and return output in TString.
Definition: TSystem.cxx:690
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:426
Base class for several text objects.
Definition: TText.h:23
virtual TText * DrawText(Double_t x, Double_t y, const char *text)
Draw this text with new coordinates.
Definition: TText.cxx:174
virtual void SetNDC(Bool_t isNDC=kTRUE)
Set NDC mode on if isNDC = kTRUE, off otherwise.
Definition: TText.cxx:812
A TTree represents a columnar dataset.
Definition: TTree.h:72
virtual Long64_t GetSelectedRows()
Definition: TTree.h:500
virtual Double_t * GetV3()
Definition: TTree.h:527
virtual Long64_t GetEntries() const
Definition: TTree.h:450
virtual void SetEstimate(Long64_t nentries=1000000)
Set number of entries to estimate variable limits.
Definition: TTree.cxx:8847
virtual Double_t * GetV1()
Definition: TTree.h:523
virtual TList * GetUserInfo()
Return a pointer to the list containing user objects associated to this tree.
Definition: TTree.cxx:6212
virtual Double_t * GetV4()
Definition: TTree.h:529
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:419
virtual Double_t * GetV2()
Definition: TTree.h:525
static constexpr double bar
static constexpr double nm
static constexpr double s
static constexpr double ns
T MinElement(Long64_t n, const T *a)
Return minimum of array a of length n.
Definition: TMath.h:942
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Definition: TMathBase.h:362
T MaxElement(Long64_t n, const T *a)
Return maximum of array a of length n.
Definition: TMath.h:949
Definition: first.py:1
Int_t fMemUsed
Definition: TSystem.h:182
Int_t fMemTotal
Definition: TSystem.h:181
auto * l
Definition: textangle.C:4