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);