78 TH1I *hleaks, *hentry;
80 TObjArray *btidlist=0;
81 Double_t *V1, *V2, *V3, *V4;
83 void EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected);
85 void memstatExample(
double update=0.01,
const char* fname=
"*") {
95 if (!fname || strlen(fname) <5 || strstr(fname,
"*")) {
97 s = gSystem->GetFromPipe(
"ls -lrt memstat*.root");
98 Int_t ns = s.Length();
99 fname = strstr(s.Data()+ns-25,
"memstat");
101 printf(
"Analyzing file: %s\n",fname);
102 f = TFile::Open(fname);
104 printf(
"Cannot open file %s\n",fname);
107 T = (TTree*)f->Get(
"T");
109 printf(
"cannot find the TMemStat TTree named T in file %s\n",fname);
113 printf(
"Illegal update value %g, changed to 0.01\n",update);
116 if (update < 0.001) printf(
"Warning update parameter is very small, processing may be slow\n");
119 Long64_t nentries = T->GetEntries();
120 T->SetEstimate(nentries+10);
121 Long64_t nsel = T->Draw(
"pos:nbytes:time:btid",
"",
"goff");
130 Long64_t imean = (Long64_t)TMath::Mean(nsel,V1);
131 Long64_t irms = (Long64_t)TMath::RMS(nsel,V1);
134 imean = imean - imean%bw;
135 irms = irms -irms%bw;
136 Int_t nbins = Int_t(4*irms/bw);
137 Long64_t ivmin = imean -bw*nbins/2;
138 Long64_t ivmax = ivmin+bw*nbins;
139 if (ivmax > 2000000000 && ivmin <2000000000) {
143 printf(
"memory locations above 2GBytes will be ignored\n");
144 nsel = T->Draw(
"pos:nbytes:time:btid",
"pos <2e9",
"goff");
149 imean = (Long64_t)TMath::Mean(nsel,V1);
150 irms = (Long64_t)TMath::RMS(nsel,V1);
152 imean = imean - imean%bw;
153 irms = irms -irms%bw;
154 nbins = Int_t(4*irms/bw);
155 ivmin = imean -bw*nbins/2;
156 ivmax = ivmin+bw*nbins;
158 update *= 0.0001*V3[nsel-1];
159 Long64_t nvm = Long64_t(ivmax-ivmin+1);
160 Long64_t *nbold =
new Long64_t[nvm];
161 Int_t *ientry =
new Int_t[nvm];
162 memset(nbold,0,nvm*8);
163 Double_t dv = (ivmax-ivmin)/nbins;
164 h =
new TH1D(
"h",Form(
"%s;pos;per cent of pages used",fname),nbins,ivmin,ivmax);
165 TAxis *axis = h->GetXaxis();
166 gStyle->SetOptStat(
"ie");
167 h->SetFillColor(kRed);
170 halloc =
new TH1D(
"halloc",Form(
"%s;pos;number of mallocs",fname),nbins,ivmin,ivmax);
171 hfree =
new TH1D(
"hfree", Form(
"%s;pos;number of frees",fname),nbins,ivmin,ivmax);
173 TCanvas *c1 =
new TCanvas(
"c1",
"c1",1200,600);
174 c1->SetFrameFillColor(kYellow-3);
179 TPaveText *pvt =
new TPaveText(.5,.9,.75,.99,
"brNDC");
182 TPaveLabel *ptime =
new TPaveLabel(.905,.7,.995,.76,
"time",
"brNDC");
183 ptime->SetFillColor(kYellow-3);
186 TNamed *named = (TNamed*)T->GetUserInfo()->FindObject(
"SysInfo");
188 tmachine.SetTextSize(0.02);
190 if (named) tmachine.DrawText(0.01,0.01,named->GetTitle());
195 Double_t dbin,rest,time;
196 Double_t updateLast = 0;
199 for (i=0;i<nsel;i++) {
201 ipos = (Long64_t)(pos-ivmin);
202 nbytes = (Int_t)V2[i];
204 bin = axis->FindBin(pos);
205 if (bin<1 || bin>nbins)
continue;
206 dbin = axis->GetBinUpEdge(bin)-pos;
209 if (dbin > nbytes) dbin = nbytes;
211 h->AddBinContent(bin,100*dbin/dv);
213 nb = Int_t((nbytes-dbin)/dv);
214 if (bin+nb >nbins) nb = nbins-bin;
215 for (j=1;j<=nb;j++) h->AddBinContent(bin+j,100);
217 rest = nbytes-nb*dv-dbin;
218 if (rest > 0) h->AddBinContent(bin+nb+1,100*rest/dv);
220 if (nbold[ipos] > 0) printf(
"reallocating %d bytes (was %lld) at %lld, entry=%d\n",nbytes,nbold[ipos],ipos,i);
221 if (nbold[ipos] == 0) {
226 nbold[ipos] = nbytes;
229 nbytes = nbold[ipos];
230 if (bin+nb >nbins) nb = nbins-bin;
231 nbold[ipos] = 0; nleaks--;
232 if (nbytes <= 0)
continue;
234 if (dbin > nbytes) dbin = nbytes;
235 h->AddBinContent(bin,-100*dbin/dv);
237 nb = Int_t((nbytes-dbin)/dv);
238 if (bin+nb >nbins) nb = nbins-bin;
239 for (j=1;j<=nb;j++) h->AddBinContent(bin+j,-100);
241 rest = nbytes-nb*dv-dbin;
242 if (rest > 0) h->AddBinContent(bin+nb+1,-100*rest/dv);
245 if (time -updateLast > update) {
250 pvt->GetListOfLines()->Delete();
254 for (Int_t k=1;k<nbins;k++) {
255 w = h->GetBinContent(k);
261 Double_t occupancy = mbytes/(nonEmpty*0.01*dv);
262 pvt->AddText(Form(
"memory used = %g Mbytes",mbytes*1e-6));
263 pvt->AddText(Form(
"page occupancy = %f per cent",occupancy));
264 pvt->AddText(
"(for non empty pages only)");
265 ptime->SetLabel(Form(
"%g sec",time));
268 gSystem->ProcessEvents();
272 Int_t nlmax = nleaks;
274 Int_t *lindex =
new Int_t[nleaks];
275 Int_t *entry =
new Int_t[nleaks];
276 Int_t *ileaks =
new Int_t[nleaks];
279 for (Int_t ii=0;ii<nvm;ii++) {
281 ileaks[nleaks] = (Int_t)nbold[ii];
282 entry[nleaks] = ientry[ii];
284 if (nleaks > nlmax)
break;
288 TMath::Sort(nleaks,ileaks,lindex);
289 hentry =
new TH1I(
"hentry",
"leak entry index",nleaks,0,nleaks);
290 hleaks =
new TH1I(
"hleaks",
"leaks;leak number;nbytes in leak",nleaks,0,nleaks);
291 for (Int_t k=0;k<nleaks;k++) {
292 Int_t kk = lindex[k];
294 hentry->SetBinContent(k+1,i);
295 hleaks->SetBinContent(k+1,ileaks[kk]);
297 hentry->SetEntries(nleaks);
298 hleaks->SetEntries(nleaks);
301 TCanvas *c2 =
new TCanvas(
"c2",
"c2",1200,600);
302 c2->SetFrameFillColor(kCyan-6);
306 hleaks->SetFillColor(kRed-3);
307 if (nleaks > 1000) hleaks->GetXaxis()->SetRange(1,1000);
310 if (named) tmachine.DrawText(0.01,0.01,named->GetTitle());
313 TRootCanvas *rc = (TRootCanvas *)c2->GetCanvasImp();
314 TGMainFrame *frm =
dynamic_cast<TGMainFrame *
>(rc);
316 if (!gTip) gTip =
new TGToolTip(gClient->GetDefaultRoot(), frm,
"", 250);
317 c2->Connect(
"ProcessedEvent(Int_t, Int_t, Int_t, TObject*)",
318 0, 0,
"EventInfo(Int_t, Int_t, Int_t, TObject*)");
323 void EventInfo(Int_t event, Int_t px, Int_t , TObject *selected)
328 if (event == kMouseLeave)
330 Double_t xpx = gPad->AbsPixeltoX(px);
331 Int_t bin = hleaks->GetXaxis()->FindBin(xpx);
332 if (bin <=0 || bin > hleaks->GetXaxis()->GetNbins())
return;
333 Int_t nbytes = (Int_t)hleaks->GetBinContent(bin);
334 Int_t entry = (Int_t)hentry->GetBinContent(bin);
335 Int_t btid = (Int_t)V4[entry];
336 Double_t time = 0.0001*V3[entry];
337 TH1I *hbtids = (TH1I*)T->GetUserInfo()->FindObject(
"btids");
339 if (!btidlist) btidlist = (TObjArray*)T->GetUserInfo()->FindObject(
"FAddrsList");
340 if (!btidlist) btidlist = (TObjArray*)f->Get(
"FAddrsList");
341 if (!btidlist)
return;
342 Int_t nbt = (Int_t)hbtids->GetBinContent(btid-1);
344 for (Int_t i=0;i<nbt;i++) {
345 Int_t j = (Int_t)hbtids->GetBinContent(btid+i);
346 TNamed *nm = (TNamed*)btidlist->At(j);
348 char *title = (
char*)nm->GetTitle();
349 Int_t nch = strlen(title);
350 if (nch < 20)
continue;
351 if (nch > 100) title[100] =0;
352 const char *bar = strstr(title,
"| ");
354 if (strstr(bar,
"operator new"))
continue;
355 if (strstr(bar,
"libMemStat"))
continue;
356 if (strstr(bar,
"G__Exception"))
continue;
357 ttip += TString::Format(
"%2d %s\n",i,bar+1);
361 TString form1 = TString::Format(
" Leak number=%d, leaking %d bytes at entry=%d time=%gseconds\n\n",bin,nbytes,entry,time);
362 gTip->SetText(TString::Format(
"%s%s",form1.Data(),ttip.Data() ));
363 gTip->SetPosition(px+15, 100);