TMemStat.cxx

Go to the documentation of this file.
00001 // @(#)root/memstat:$Name$:$Id: TMemStat.cxx 29439 2009-07-10 13:52:26Z brun $
00002 // Author: M.Ivanov   18/06/2007 -- Anar Manafov (A.Manafov@gsi.de) 29/04/2008
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 ////////////////////////////////////////////////////////////////////////////////
00013 /* BEGIN_HTML
00014 <center><h2>The TMemStat class</h2></center>
00015 TMemStat  - a class for visualization of the memory usage.
00016 <br/>
00017 Principle:
00018 Hook functions for malloc and free are used.
00019 All calls to malloc and free are caught and the statistical information is collected.
00020 The information is collected per stack trace (Unique identifier and per functions).<br/>
00021 Following information are collected as function of time:
00022 <ul>
00023     <li>Total number of allocations</li>
00024     <li>Total allocation size</li>
00025     <li>Allocation count</li>
00026     <li>Allocation size</li>
00027 </ul>
00028 How to use it:<br/>
00029 To create a memstat object use the following:
00030 <pre>
00031     TMemStat memstat("new");
00032 </pre>
00033 Possible options:
00034 <ul>
00035     <li> "new" - Start new data collection. In the current release a hard-coded "memstat.root" file will be created or overwritten if exists.</li>
00036     <li> "read" - "read" - analyze previously collected data.</li>
00037     <li>"gnubuildin" - if declared, then TMemStat will use gcc build-in function, otherwise glibc backtrace will be used.</li>
00038 </ul>
00039 A user may want to request for adding the named memory stamp:
00040 <pre>
00041     memstat.AddStamp("STEMPNAME")
00042 </pre>
00043 The file "memstat.root" is created after destruction of object.<br/>
00044 This class supports following  functions for standard user:
00045 <ul>
00046     <li> Report </li>
00047     <li> Draw </li>
00048     <li> SelectCode(libname, functionname) </li>
00049     <li> SelectStack() </li>
00050 </ul>
00051 The various format options to draw a Graph  can be accessed calling
00052 <pre>
00053     TMemStat memstat;
00054     memstat.Report("?")
00055 </pre>
00056 
00057 Supported options for TMemStat::Report:
00058 <ul>
00059     <li> order     : 0=increasing,  1=decreasing</li>
00060     <li> sortstat  : 0=TotalAllocCount, 1=TotalAlocSize,  2=AllocCount, 3=AllocSize</li>
00061     <li> sortstamp : 0=Current, 1=MaxSize,  2=MaxCount</li>
00062     <li> sortdeep  : (0-inf) number of info to print</li>
00063     <li> stackdeep : (0-inf) deepness of stack</li>
00064     <li> Example   : order 0 sortstat 3 sortstamp 0 sortdeep 10 stackdeep 5 maxlength 50 </li>
00065 </ul>
00066 
00067 
00068 The picture below gives an example:
00069 END_HTML
00070 BEGIN_MACRO(source)
00071 {
00072    {
00073       TMemStat memstat("new,gnubuildin");
00074 
00075       for (Int_t i=0;i<11000;i++) {
00076          TObjString * object = new TObjString(Form("Object%d",i));
00077          if (i%2) delete object;
00078       }
00079       for (Int_t i=0;i<12000;i++) {
00080          TString * object2 = new TString(i);
00081          if (i%2) delete object2;
00082       }
00083       for (Int_t i=0;i<1300;i++) {
00084          TClonesArray  *array = new TClonesArray("TVectorD");
00085          //array.ExpandCreatFast(i);
00086       }
00087    }
00088 
00089    TMemStat report;
00090    report->Report();
00091 }
00092 END_MACRO */
00093 ////////////////////////////////////////////////////////////////////////////////
00094 
00095 // STD
00096 #include <map>
00097 #include <vector>
00098 #include <iostream>
00099 // ROOT
00100 #include "TTree.h"
00101 #include "TMath.h"
00102 #include "TArrayI.h"
00103 #include "TBits.h"
00104 #include "TDirectory.h"
00105 #include "TCanvas.h"
00106 #include "TAxis.h"
00107 #include "TGraph.h"
00108 #include "TLegend.h"
00109 #include "TText.h"
00110 #include "TLine.h"
00111 #include "THStack.h"
00112 #include "TSystem.h"
00113 
00114 #include "TMemStat.h"
00115 #include "TMemStatInfo.h"
00116 #include "TMemStatManager.h"
00117 #include "TMemStatHelpers.h"
00118 
00119 
00120 ClassImp(TMemStat)
00121 
00122 using namespace std;
00123 using namespace Memstat;
00124 
00125 static char *ginfo = 0;
00126 
00127 typedef vector<Long64_t> Long64Vector_t;
00128 typedef vector<Double_t> DoubleVector_t;
00129 
00130 _INIT_TOP_STECK;
00131 
00132 struct SFillSelection: public binary_function<
00133          TMemStatManager::CodeInfoContainer_t::value_type,
00134          TMemStat::ESelection,
00135          TMemStat::Selection_t::value_type>
00136 {
00137    TMemStat::Selection_t::value_type operator() (
00138       const TMemStatManager::CodeInfoContainer_t::value_type &_code_info,
00139       TMemStat::ESelection _Selection ) const
00140    {
00141       switch ( _Selection )
00142       {
00143       case TMemStat::kFunction:
00144          return _code_info.fFunction.Data();
00145       case TMemStat::kLibrary:
00146          // we need only names of libraries
00147          return gSystem->BaseName(_code_info.fLib.Data());
00148       default:
00149          return string();
00150       }
00151    }
00152 };
00153 
00154 //______________________________________________________________________________
00155 TMemStat::TMemStat(Option_t* option):
00156       TObject(),
00157       fSortStat(kAllocSize),
00158       fSortStamp(kCurrent),
00159       fMaximum(0),
00160       fSortDeep(10),
00161       fStackDeep(20),
00162       fMaxStringLength(50),
00163       fSelected(0),
00164       fIsActive(kFALSE),
00165       fOrder(kFALSE),
00166       fSelectedCodeBitmap(NULL),
00167       fSelectedStackBitmap(NULL),
00168       fStampArray(NULL),
00169       fArray(NULL),
00170       fArrayGraphics(NULL),
00171       fTree(NULL),
00172       fTreeSys(NULL),
00173       fStackSummary(NULL),
00174       fManager(NULL)
00175 {
00176    // Supported options:
00177    //    "new" - start to collect memory allocations stamps
00178    //    "read" - analyze previously collected data
00179    //    "gnubuildin" - if declared, then TMemStat will use gcc build-in function,
00180    //                      otherwise glibc backtrace will be used
00181    //
00182    // Default: "read"
00183    // Note: Currently TMemStat uses a hard-coded output file name (for writing/reading) = "memstat.root";
00184 
00185    // It marks the highest used stack address.
00186    _GET_TO_STECK;
00187 
00188    //preserve context. When exiting will restore the current directory
00189    TDirectory::TContext context(gDirectory);
00190 
00191    string opt(option);
00192    transform( opt.begin(), opt.end(), opt.begin(),
00193               Memstat::ToLower_t() );
00194 
00195    if ( opt.find("new") != string::npos) // Processing "NEW"
00196    {
00197       SetAutoStamp();
00198       const Bool_t useBuildin = (opt.find("gnubuildin") != string::npos)? kTRUE: kFALSE;
00199       TMemStatManager::GetInstance()->SetUseGNUBuildinBacktrace(useBuildin);
00200       TMemStatManager::GetInstance()->Enable();
00201       // set this variable only if "NEW" mode is active
00202       fIsActive = kTRUE;
00203    }
00204    else if ( opt.find("read") != string::npos) // Processing "READ"
00205    {
00206       // GetData from existing file
00207       GetMemStat("memstat.root", -1);
00208 
00209       // default disabling
00210       fDisablePrintLib.SetOwner();
00211       fDisablePrintLib.AddLast(new TObjString("libRIO"));
00212       fDisablePrintCode.SetOwner();
00213       fDisablePrintCode.AddLast(new TObjString("TClass::Streamer"));
00214       // set default option
00215       ProcessOption("order 0 sortstat 3 sortstamp 0 sortdeep 30 stackdeep 15 maxlength 50");
00216    }
00217    else
00218    {
00219       Error("TMemStat", "Invalid option");
00220    }
00221 }
00222 
00223 //______________________________________________________________________________
00224 TMemStat::~TMemStat()
00225 {
00226    // destructor
00227 
00228    if (fIsActive) {
00229       TMemStatManager::GetInstance()->Disable();
00230       TMemStatManager::GetInstance()->Close();
00231    }
00232 
00233    delete fStackSummary;
00234    delete fSelectedCodeBitmap;
00235    delete fSelectedStackBitmap;
00236 }
00237 
00238 //______________________________________________________________________________
00239 void TMemStat::AddStamp(const char*stampName)
00240 {
00241    // Add named stamp to the file
00242 
00243    TMemStatManager::GetInstance()->AddStamps(stampName);
00244 }
00245 
00246 //______________________________________________________________________________
00247 Int_t TMemStat::DistancetoPrimitive(Int_t px, Int_t py)
00248 {
00249    // Return distance of the mouse to the TMemStat object
00250    
00251    const Int_t big = 9999;
00252    if (!fArray) return big;
00253 
00254    Int_t mindist = big;
00255    for (Int_t i = 0; i < fArray->GetSize(); ++i) {
00256       TObject *obj = fArray->At(i);
00257       if (!obj) continue;
00258       Int_t dist = obj->DistancetoPrimitive(px, py);
00259       if (dist < mindist) mindist = dist;
00260    }
00261    return mindist;
00262 }
00263 
00264 //______________________________________________________________________________
00265 void TMemStat::Draw(Option_t *option)
00266 {
00267    // Draw the memory statistic
00268    // call ::Report("?") to see possible options and meaning
00269 
00270      TString opt(option);
00271      opt.ToLower();
00272      if (opt.Contains("?"))
00273         return;
00274      
00275      TLegend *legend = 0;
00276      if (!gPad) {
00277         TCanvas *c = new TCanvas;
00278         c->SetGrid();
00279         if (gROOT->IsBatch()) {
00280            c->SetTopMargin(0.2);
00281            c->SetRightMargin(0.3);
00282            c->SetLeftMargin(0.10);
00283            legend = new TLegend(0.75, 0.1, 0.99, 0.9, "Memory statistic");
00284         } else {
00285            c->ToggleToolTips();
00286         }   
00287      } else {
00288         gPad->GetListOfPrimitives()->Remove(this);
00289         gPad->Clear();
00290      }
00291 
00292      ProcessOption(option);
00293 
00294      RefreshSelect();
00295 
00296      if (!opt.Contains("code")) {
00297         SortStack(fSortStat, fSortStamp);
00298         fArray = MakeGraphStack(fSortStat, fSortDeep);
00299      } else {
00300         SortCode(fSortStat, fSortStamp);
00301         fArray = MakeGraphCode(fSortStat, fSortDeep);
00302      }
00303 
00304      
00305      Bool_t gDone = kFALSE;
00306      MakeStampsText();
00307      if (gPad) {
00308         for (Int_t i = 0;i < fArray->GetEntries();i++) {
00309            TObject *obj = fArray->At(i);
00310            if (!obj) continue;
00311            if (!gDone) {
00312               obj->Draw("alp");
00313               ((TGraph*)obj)->SetMaximum(1.1*fMaximum);
00314               gDone = kTRUE;
00315            } else {
00316               obj->Draw("lp");
00317            }
00318            cout << i << '\t' << obj->GetName() << endl;
00319            if (legend) legend->AddEntry(obj, obj->GetName());
00320         }
00321         if (!gROOT->IsBatch()) {AppendPad(); gPad->Update(); return;}
00322         
00323         gPad->Update();
00324         if (legend) legend->Draw();
00325         fArray->AddLast(legend);
00326         Int_t ng = 0;
00327         if (fArrayGraphics) ng = fArrayGraphics->GetEntries();
00328         
00329         for (Int_t i = 0; i < ng; i++) {
00330            TText *ptext = dynamic_cast<TText*>(fArrayGraphics->At(i));
00331            if (ptext) {
00332               ptext->SetY(gPad->GetUymax());
00333               ptext->SetTextAngle(45);
00334               ptext->SetTextSizePixels(12);
00335               ptext->SetTextAlign(13);
00336               ptext->Draw("");
00337            }
00338            TLine *pline = dynamic_cast<TLine*>(fArrayGraphics->At(i));
00339            if (pline) {
00340               pline->SetY2(gPad->GetUymax());
00341               pline->SetLineStyle(2);
00342               pline->Draw("");
00343            }
00344         }
00345      }
00346      AppendPad();
00347 }
00348 
00349 //______________________________________________________________________________
00350 Bool_t TMemStat::EnabledCode(const TMemStatCodeInfo &info) const
00351 {
00352    // Private function
00353    // disable printing of the predefined code sequence
00354    if (info.fLib.Contains("libMemStat.so"))
00355       return kFALSE;
00356    if (info.fFunction.Contains("operator new"))
00357       return kFALSE;
00358    if (info.fFunction.Contains("TMethodCall::Execute"))
00359       return kFALSE;
00360    if (info.fFunction.Contains("Cint::G__CallFunc::Exec"))
00361       return kFALSE;
00362    if (info.fFunction.Contains("Cint::G__ExceptionWrapper"))
00363       return kFALSE;
00364    if (info.fFunction.Sizeof() <= 1)
00365       return kFALSE;
00366 
00367    for (Int_t i = 0; i < fDisablePrintLib.GetEntries(); ++i) {
00368       TObjString * str = (TObjString*)fDisablePrintLib.At(i);
00369       if (str && info.fLib.Contains(str->String().Data()))
00370          return kFALSE;
00371    }
00372 
00373    for (Int_t i = 0; i < fDisablePrintCode.GetEntries(); ++i) {
00374       TObjString * str = (TObjString*)fDisablePrintCode.At(i);
00375       if (str && info.fFunction.Contains(str->String().Data()))
00376          return kFALSE;
00377    }
00378 
00379    return kTRUE;
00380 }
00381 
00382 //______________________________________________________________________________
00383 void TMemStat::ExecuteEvent(Int_t /*event*/, Int_t /* px*/, Int_t /*py*/)
00384 {
00385    // function called when clicking with the mouse on a TMemStat object
00386 
00387    // TODO: this method needs to be revised
00388    /* switch (event) {
00389     case kButton1Down:
00390        if (fArray && fSelected >= 0) {
00391           const Int_t uid = fArrayIndexes[fSelected];
00392           cout << endl;
00393           (uid >= 0) ? PrintStackWithID(uid) : PrintCodeWithID(-uid);
00394        }
00395        break;
00396     case kMouseMotion:
00397        break;
00398     case kButton1Motion:
00399        break;
00400     case kButton1Up:
00401        break;
00402     }*/
00403 }
00404 
00405 //______________________________________________________________________________
00406 void TMemStat::GetFillSelection(Selection_t *_Container, ESelection _Selection) const
00407 {
00408    // TODO: Comment me
00409 
00410    if ( !_Container || !fManager)
00411       return;
00412 
00413    transform( fManager->fCodeInfoArray.begin(),
00414               fManager->fCodeInfoArray.end(),
00415               inserter(*_Container, _Container->begin()),
00416               bind2nd(SFillSelection(), _Selection) );
00417 }
00418 
00419 //______________________________________________________________________________
00420 Bool_t TMemStat::GetMemStat(const char * fname, Int_t entry)
00421 {
00422    // Get memstat from tree
00423 
00424    if (fname != 0) {
00425       fFile.reset(TFile::Open(fname));
00426       if (!fFile.get() || fFile->IsZombie())
00427          return kFALSE;
00428 
00429       fTree = dynamic_cast<TTree*>(fFile->Get("MemStat"));
00430       if (!fTree)
00431          return kFALSE;
00432 
00433       fTreeSys = dynamic_cast<TTree*>(fFile->Get("MemSys"));
00434       if (!fTreeSys)
00435          return kFALSE;
00436    }
00437 
00438    TMemStatManager *man(NULL);
00439    // TODO: needs to be investigated.
00440    // There was a crash, happens when user reselect stamps list after TMemStat Draw has been called.
00441    // The crash (SEGFAULT) happens in fTree->GetEntry(entry) in access of its buffer.
00442    // ResetBranchAddresses helped, but it is not clear whether this fix correct or not.
00443    fTree->ResetBranchAddresses();
00444    fTree->SetBranchAddress("Manager", &man);
00445 
00446    if ( (entry < 0) || (entry >= fTree->GetEntries()) )
00447       entry = fTree->GetEntries() - 1;
00448 
00449    fTree->GetEntry(entry);
00450    fManager = man;
00451    return kTRUE;
00452 }
00453 
00454 
00455 //______________________________________________________________________________
00456 char *TMemStat::GetObjectInfo(Int_t px, Int_t py) const
00457 {
00458    //Display the stack trace info corresponding to the graph at cursor position px,py.
00459 
00460    if (!gPad || !fArray) return (char*)"";
00461    if (!ginfo) ginfo = new char[10000];
00462    const Int_t big = 9999;
00463 
00464    Int_t mindist = big;
00465    TObject *objmin = 0;
00466    Int_t imin = 0;
00467    for (Int_t i = 0; i < fArray->GetSize(); ++i) {
00468       TObject *obj = fArray->At(i);
00469       if (!obj) continue;
00470       Int_t dist = obj->DistancetoPrimitive(px, py);
00471       if (dist < mindist) {mindist = dist; objmin = obj;imin=i;}
00472    }
00473 
00474    if (objmin) {
00475       sprintf(ginfo,"-");
00476       const TMemStatStackInfo &infoStack = fManager->fStackVector[objmin->GetUniqueID()];
00477       for (UInt_t icode = 0, counter = 0; icode < infoStack.fSize; ++icode) {
00478          const TMemStatCodeInfo &infoCode(fManager->fCodeInfoArray[infoStack.fSymbolIndexes[icode]]);
00479          if (!EnabledCode(infoCode)) continue;
00480          strcat(ginfo,infoCode.fFunction.Data()); strcat(ginfo,"\n");
00481          ++counter;
00482          if (counter >= 5) break;
00483       }
00484       return ginfo;
00485    }
00486    return (char*)"";
00487 }
00488 
00489 //______________________________________________________________________________
00490 TObjArray* TMemStat::GetStampList()
00491 {
00492    // TODO: Comment me
00493    if (fStampArray)
00494       return fStampArray;
00495 
00496    if (!fTreeSys)
00497       return NULL;
00498 
00499    TObjString str;
00500    TObjString *pstr = &str;
00501    fStampArray = new TObjArray;
00502    fTreeSys->SetBranchAddress("StampName.", &pstr);
00503    for (Int_t i = 0; i < fTreeSys->GetEntries(); ++i) {
00504       fTreeSys->GetEntry(i);
00505       fStampArray->AddLast(str.Clone());
00506    }
00507    return fStampArray;
00508 }
00509 
00510 //______________________________________________________________________________
00511 void TMemStat::MakeCodeArray()
00512 {
00513    //   PRIVATE: make code index accoring tbit mask
00514 
00515    if (!fManager)
00516       return;
00517 
00518    Int_t nselected = 0;
00519    size_t csize = fManager->fCodeInfoArray.size();
00520 
00521    for (UInt_t i = 0; i < csize; ++i)
00522       if (fSelectedCodeBitmap->TestBitNumber(i))
00523          ++nselected;
00524 
00525    fSelectedCodeIndex.clear();
00526    fSelectedCodeIndex.reserve(nselected);
00527    for (UInt_t i = 0; i < csize; ++i) {
00528       if (fSelectedCodeBitmap->TestBitNumber(i))
00529          fSelectedCodeIndex.push_back(i);
00530    }
00531 }
00532 
00533 //______________________________________________________________________________
00534 void TMemStat::MakeStackArray()
00535 {
00536    //   PRIVATE: make code index according tbit mask
00537 
00538    if (!fManager)
00539       return;
00540 
00541    delete fStackSummary;
00542    fStackSummary = new TMemStatInfoStamp();
00543 
00544    fSelectedStackIndex.clear();
00545 
00546    const size_t csize = fManager->fStackVector.size();
00547    for (size_t i = 0; i < csize; ++i) {
00548       if (fSelectedStackBitmap->TestBitNumber(i)) {
00549          fSelectedStackIndex.push_back(i);
00550          const TMemStatStackInfo &info = fManager->fStackVector[i];
00551          fStackSummary->fTotalAllocCount += info.fCurrentStamp.fTotalAllocCount;
00552          fStackSummary->fTotalAllocSize += info.fCurrentStamp.fTotalAllocSize;
00553          fStackSummary->fAllocCount += info.fCurrentStamp.fAllocCount;
00554          fStackSummary->fAllocSize += info.fCurrentStamp.fAllocSize;
00555       }
00556    }
00557 }
00558 
00559 
00560 
00561 //______________________________________________________________________________
00562 TObjArray *TMemStat::MakeGraphCode(StatType statType, Int_t nentries)
00563 {
00564    // make array of graphs
00565 
00566    if (fArray) {
00567       fArray->Delete();
00568       delete fArray;
00569    }
00570    fArray  = new TObjArray(nentries);
00571 
00572    fArrayIndexes.clear();
00573    fArrayIndexes.resize(nentries);
00574 
00575    Int_t count = 0;
00576    Int_t first = TMath::Max(static_cast<Int_t>(fSelectedCodeIndex.size()) - nentries, 0);
00577    Double_t cxmax, cymax;
00578    for (Int_t i = fSelectedCodeIndex.size() - 1; i > first; --i) {
00579       TGraph * gr = MakeGraph(statType, fSelectedCodeIndex[i], TMemStatInfoStamp::kCode, cxmax, cymax);
00580       if (!gr)
00581          continue;
00582       TMemStatCodeInfo  &cinfo =  fManager->fCodeInfoArray[fSelectedCodeIndex[i]];
00583       if (cinfo.fFunction.Length() > 0) {
00584          TString str(cinfo.fFunction);
00585          if ((UInt_t)(str.Length()) > fMaxStringLength)
00586             str.Resize(fMaxStringLength);
00587          gr->SetName(str);
00588       }
00589       ++count;
00590       gr->SetLineColor(count % 5 + 1);
00591 
00592       fArrayIndexes[fArray->GetEntries()] = -fSelectedCodeIndex[i];
00593       fArray->AddLast(gr);
00594    }
00595    return fArray;
00596 }
00597 
00598 //______________________________________________________________________________
00599 TObjArray *TMemStat::MakeGraphStack(StatType statType, Int_t nentries)
00600 {
00601    // make array of graphs
00602 
00603    if (fArray) {
00604       fArray->Delete();
00605       delete fArray;
00606    }
00607    fArray = new TObjArray(nentries);
00608 
00609    fArrayIndexes.clear();
00610    fArrayIndexes.resize(nentries);
00611 
00612    Int_t count = 0;
00613    const Int_t first = TMath::Max(static_cast<int>(fSelectedStackIndex.size()) - nentries, 0);
00614    Double_t cxmax(0);
00615    Double_t cymax(0);
00616    fMaximum = 0;
00617    for (Int_t i = fSelectedStackIndex.size() - 1; i > first; --i) {
00618       TGraph * gr = MakeGraph(statType, fSelectedStackIndex[i], TMemStatInfoStamp::kStack, cxmax, cymax);
00619       if (!gr)
00620          continue;
00621       if (cymax > fMaximum) fMaximum = cymax;
00622       TMemStatStackInfo &infoStack = fManager->fStackVector[(fSelectedStackIndex[i])];
00623       for (UInt_t icode = 0; icode < infoStack.fSize; icode++) {
00624          TMemStatCodeInfo &infoCode = fManager->fCodeInfoArray[infoStack.fSymbolIndexes[icode]];
00625          if (EnabledCode(infoCode)) {
00626             if (infoCode.fFunction) {
00627                TString str(infoCode.fFunction);
00628                if ((UInt_t)(str.Length()) > fMaxStringLength) str.Resize(fMaxStringLength);
00629                gr->SetName(str);
00630                gr->SetUniqueID(fSelectedStackIndex[i]);
00631             }
00632             break;
00633          }
00634       }
00635       ++count;
00636       gr->SetLineColor(count % 5 + 1);
00637       gr->SetMarkerColor(count % 5 + 1);
00638       gr->SetMarkerStyle(20 + count % 5);
00639       gr->SetMarkerSize(0.15);
00640       fArrayIndexes[fArray->GetEntries()] = fSelectedStackIndex[i];
00641       fArray->AddLast(gr);
00642    }
00643 
00644    return fArray;
00645 }
00646 
00647 //______________________________________________________________________________
00648 TGraph *TMemStat::MakeGraph(StatType statType, Int_t id, Int_t type, Double_t &xmax, Double_t &ymax)
00649 {
00650    // Make graph
00651 
00652    if (!fTree)
00653       return 0;
00654 
00655    string sWhat;
00656    string sWhatName;
00657    switch (statType) {
00658    case kTotalAllocCount:
00659       sWhat = "fStampVector.fTotalAllocCount:fStampVector.fStampNumber";
00660       sWhatName = "TotalAllocCount";
00661       break;
00662    case kAllocCount:
00663       sWhat = "fStampVector.fAllocCount:fStampVector.fStampNumber";
00664       sWhatName = "AllocCount";
00665       break;
00666    case kTotalAllocSize:
00667       sWhat = "fStampVector.fTotalAllocSize/1000000.:fStampVector.fStampNumber";
00668       sWhatName = "TotalAllocSize (MBy)";
00669       break;
00670    case kAllocSize:
00671       sWhat = "fStampVector.fAllocSize/1000000.:fStampVector.fStampNumber";
00672       sWhatName = "AllocSize (MBy)";
00673       break;
00674    case kUndef:
00675       // TODO: check this case; in original code it wasn't handled
00676       break;
00677    }
00678    ostringstream ssWhere;
00679    ssWhere << "fStampVector.fID==" << id << "&&fStampVector.fStampType==" << type;
00680 
00681    const Int_t entries = fTree->Draw(sWhat.c_str(), ssWhere.str().c_str(), "goff");
00682    if (entries <= 0)
00683       return 0;
00684 
00685    const Int_t maxStamp = fManager->fStampNumber;
00686 
00687    Float_t *x = new Float_t[maxStamp];
00688    Float_t *y = new Float_t[maxStamp];
00689    xmax = 0;
00690    ymax = 0;
00691    Float_t last = 0;
00692    for (Int_t i = 0, counter = 0; i < maxStamp; ++i) {
00693       x[i] = i;
00694       y[i] = last;
00695       if (y[i] > ymax) ymax = y[i];
00696       if (x[i] > xmax) xmax = x[i];
00697       if (counter >= entries)
00698          continue;
00699       if (fTree->GetV2()[counter] > i) {
00700          y[i] = last;
00701       } else {
00702          y[i] = fTree->GetV1()[counter];
00703          last = y[i];
00704          ++counter;
00705       }
00706    }
00707    TGraph * graph  = new TGraph(maxStamp, x, y);
00708    graph->GetXaxis()->SetTitle("StampNumber");
00709    graph->GetYaxis()->SetTitle(sWhatName.c_str());
00710    return graph;
00711 }
00712 
00713 //______________________________________________________________________________
00714 void TMemStat::MakeHisMemoryStamp(Int_t /*topDiff*/)
00715 {
00716    //draw histogram of memory usage as function of stamp name
00717    // NOT IMPLEMENTED YET
00718 
00719    const Int_t entries = fTreeSys->Draw("Mem3", "Mem3>0", "");
00720    DoubleVector_t diff(entries - 1);
00721    for (Int_t i = 0; i < entries - 1; ++i) {
00722       diff[i] = fTreeSys->GetV1()[i+1] - fTreeSys->GetV1()[i];
00723    }
00724    IntVector_t indexes(entries - 1);
00725    TMath::Sort(entries - 1, &diff[0], &indexes[0], kFALSE);
00726 }
00727 
00728 //______________________________________________________________________________
00729 void TMemStat::MakeHisMemoryTime()
00730 {
00731    // Make dump of memory usage versus time
00732 
00733    fTreeSys->Draw("Mem3:StampTime.fSec>>hhh", "", "goff*");
00734    if (!gROOT->FindObject("hhh"))
00735       return ;
00736 
00737    TH1* his3 = (TH1*)gROOT->FindObject("hhh")->Clone("Virtual Memory");
00738    his3->SetDirectory(0);
00739    delete gROOT->FindObject("hhh");
00740 
00741    fTreeSys->Draw("Mem2:StampTime.fSec>>hhh", "", "goff*");
00742    if (!gROOT->FindObject("hhh"))
00743       return ;
00744 
00745    TH1* his2 = (TH1*)gROOT->FindObject("hhh")->Clone("Residual Memory");
00746    his2->SetDirectory(0);
00747    delete gROOT->FindObject("hhh");
00748 
00749    fTreeSys->Draw("CurrentStamp.fAllocSize/1000000.:StampTime.fSec>>hhh", "", "goff*");
00750    if (!gROOT->FindObject("hhh"))
00751       return ;
00752 
00753    TH1* hism = (TH1*)gROOT->FindObject("hhh")->Clone("Allocated Memory");
00754    hism->SetDirectory(0);
00755    delete gROOT->FindObject("hhh");
00756 
00757    his3->GetXaxis()->SetTimeDisplay(1);
00758    his3->SetMarkerColor(2);
00759    his2->SetMarkerColor(3);
00760    hism->SetMarkerColor(4);
00761    his3->Draw();
00762    his2->Draw("same");
00763    hism->Draw("same");
00764 }
00765 
00766 //______________________________________________________________________________
00767 void TMemStat::MakeReport(const char * lib, const char *fun, Option_t* option, const char *fileName)
00768 {
00769    // make report for library
00770 
00771    // reset selection
00772    SelectCode(NULL, NULL, TMemStat::kOR);
00773    SelectStack(TMemStat::kOR);
00774    //
00775    SelectCode(lib, fun, TMemStat::kAND);
00776    SelectStack(TMemStat::kAND);
00777    if (option)
00778       ProcessOption(option);
00779    SortCode(fSortStat, fSortStamp);
00780    SortStack(fSortStat, fSortStamp);
00781 
00782    // Redirecting the output if needed
00783    if (strlen(fileName) > 0)
00784       gSystem->RedirectOutput(fileName, "w");
00785 
00786    Report();
00787 
00788    if (strlen(fileName) > 0)
00789       gSystem->RedirectOutput(0);
00790 }
00791 
00792 //______________________________________________________________________________
00793 void TMemStat::MakeStampsText()
00794 {
00795    // Make a text description of the stamps
00796    // create a array of TText objects
00797 
00798    // TODO: see TMemStat::Draw
00799    /*if (!fArrayGraphics)
00800        fArrayGraphics = new TObjArray();
00801 
00802     const Int_t nentries = fTree->GetEntries();
00803     Int_t stampNumber(0);
00804     TObjString *pnameStamp(NULL);
00805     TTimeStamp *ptimeStamp(NULL);
00806     fTree->SetBranchAddress("StampTime.", &ptimeStamp);
00807     fTree->SetBranchAddress("StampName.", &pnameStamp);
00808     fTree->SetBranchAddress("StampNumber", &stampNumber);
00809 
00810     for (Int_t i = 0; i < nentries; ++i) {
00811        fTree->GetBranch("StampTime.")->GetEntry(i);
00812        fTree->GetBranch("StampName.")->GetEntry(i);
00813        fTree->GetBranch("StampNumber")->GetEntry(i);
00814        char chname[1000];
00815        if (pnameStamp->GetString().Contains("autoStamp")) {
00816           sprintf(chname, " ");
00817        } else {
00818           sprintf(chname, "%s  %d", pnameStamp->GetString().Data(), ptimeStamp->GetTime());
00819        }
00820        TText *ptext = new TText(stampNumber, 0, chname);
00821        fArrayGraphics->AddLast(ptext);
00822        TLine * pline = new TLine(stampNumber, 0, stampNumber, 1);
00823        fArrayGraphics->AddLast(pline);
00824     }*/
00825 }
00826 
00827 //______________________________________________________________________________
00828 void TMemStat::Paint(Option_t * /* option */)
00829 {
00830    // Paint function
00831 }
00832 
00833 //______________________________________________________________________________
00834 void TMemStat::PrintCode(Int_t nentries) const
00835 {
00836    // Print information about n selected functions
00837    // If the number of function selected is bigger than number n
00838    // the only top (sorted accoring some creteria,) n are displayed
00839    // e.g draw.SortCode(TMemStat::kAllocSize,TMemStat::kCurrent);
00840    if (fSelectedCodeIndex.empty() || !fManager)
00841       return;
00842 
00843    UIntVector_t::const_iterator iter = max((fSelectedCodeIndex.end() - nentries), fSelectedCodeIndex.begin());
00844    UIntVector_t::const_iterator iter_end = fSelectedCodeIndex.end();
00845    for (; iter != iter_end; ++iter)
00846       fManager->fCodeInfoArray[*iter].Print();
00847 }
00848 
00849 //______________________________________________________________________________
00850 void TMemStat::PrintCodeWithID(UInt_t id) const
00851 {
00852    // print information for code with ID
00853 
00854    if (!fManager)
00855       return;
00856    if (id > fManager->fCodeInfoArray.size())
00857       return;
00858    fManager->fCodeInfoArray[id].Print();
00859 }
00860 
00861 //______________________________________________________________________________
00862 void TMemStat::PrintStack(Int_t nentries, UInt_t deep) const
00863 {
00864    // Print information about n selected stack traces
00865    // If the number of function selected is bigger than number n
00866    // the only top (sorted according some criteria) n are displayed
00867    // e.g draw.SortCode(TMemStat::kAllocSize,TMemStat::kCurrent);
00868    if (fSelectedStackIndex.empty())
00869       return;
00870 
00871    UIntVector_t::const_iterator iter = max((fSelectedStackIndex.end() - nentries), fSelectedStackIndex.begin());
00872    UIntVector_t::const_iterator iter_end = fSelectedStackIndex.end();
00873    for (; iter != iter_end; ++iter)
00874       PrintStackWithID(*iter, deep);
00875 
00876    cout << "Summary for selected:" << endl;
00877    ios::fmtflags old_flags(cout.flags(ios::left));
00878    fStackSummary->Print();
00879    cout.flags(old_flags);
00880 }
00881 
00882 
00883 //______________________________________________________________________________
00884 void TMemStat::PrintStackWithID(UInt_t _id, UInt_t _deep) const
00885 {
00886    // print stack information for code with ID
00887    // NOTE: if _deep is 0, then we use fStackDeep
00888    if (!fManager)
00889       return;
00890 
00891    _deep = !_deep ? fStackDeep : _deep;
00892 
00893    const TMemStatStackInfo &infoStack = fManager->fStackVector[_id];
00894    cout << infoStack << endl;
00895 
00896    ios::fmtflags old_flags(cout.flags(ios::left));
00897    for (UInt_t icode = 0, counter = 0; icode < infoStack.fSize; ++icode) {
00898       const TMemStatCodeInfo &infoCode(fManager->fCodeInfoArray[infoStack.fSymbolIndexes[icode]]);
00899       if (!EnabledCode(infoCode))
00900          continue;
00901       cout
00902       << setw(5) << icode
00903       << infoCode << endl;
00904       ++counter;
00905       if (counter >= _deep)
00906          break;
00907    }
00908    cout.flags(old_flags);
00909 }
00910 
00911 //______________________________________________________________________________
00912 void TMemStat::ProcessOption(Option_t *option)
00913 {
00914    // PRIVATE function
00915    // process user option string for printing
00916 
00917    TString str(option);
00918    TString delim(" ");
00919    TObjArray *tokens = str.Tokenize(delim);
00920    for (Int_t i = 0; i < tokens->GetEntriesFast() - 1; ++i) {
00921       TObjString *strTok = (TObjString*)tokens->At(i);
00922       TObjString *strNum = (i < tokens->GetEntriesFast()) ? (TObjString*)tokens->At(i + 1) : 0;
00923 
00924       if (strNum && strNum->String().IsDigit()) {
00925          if (strTok->String().Contains("sortstat")) {
00926             Int_t val = strNum->String().Atoi();
00927             if (val > 3) {
00928                Error("SetOption", Form("Invalid value for sortstat %d", val));
00929                val = 3;
00930             }
00931             fSortStat = (TMemStat::StatType)val;
00932          }
00933          if (strTok->String().Contains("sortstamp")) {
00934             Int_t val = strNum->String().Atoi();
00935             if (val > 2) {
00936                Error("SetOption", Form("Invalid value for sortstamp %d", val));
00937                val = 0;
00938             }
00939             fSortStamp = (TMemStat::StampType)val;
00940          }
00941 
00942          if (strTok->String().Contains("order")) {
00943             Int_t val = strNum->String().Atoi();
00944             if (val > 1) {
00945                Error("SetOption", Form("Invalid sorting value", val));
00946                val = 0;
00947             }
00948             fOrder = (val > 0);
00949          }
00950          if (strTok->String().Contains("sortdeep")) {
00951             fSortDeep = strNum->String().Atoi();
00952          }
00953          if (strTok->String().Contains("stackdeep")) {
00954             fStackDeep  = strNum->String().Atoi();
00955          }
00956          if (strTok->String().Contains("maxlength")) {
00957             fMaxStringLength  = strNum->String().Atoi();
00958          }
00959       }
00960    }
00961    char currentOption[1000];
00962    sprintf(currentOption, "order %d sortstat %d sortstamp %d sortdeep %d stackdeep %d maxlength %d",
00963            fOrder, fSortStat, fSortStamp, fSortDeep, fStackDeep, fMaxStringLength);
00964    fOption = currentOption;
00965    if (str.Contains("?")) {
00966       printf("Options   : %s\n", fOption.Data());
00967       printf("order     : 0 - increasing 1 - decreasing\n");
00968       printf("sortstat  : 0 - TotalAllocCount 1 -  TotalAlocSize  2 - AllocCount 3 - AllocSize\n");
00969       printf("sortstamp : 0 - Current 1 -  MaxSize  2 - MaxCount\n");
00970       printf("sortdeep  : (0-inf) number of info to print\n");
00971       printf("stackdeep : (0-inf) deepnes of stack\n");
00972       printf("maxlength : (0-inf) maximal length of function (truncation after maxlength)");
00973    }
00974 
00975    delete tokens;
00976 }
00977 
00978 //______________________________________________________________________________
00979 void TMemStat::RefreshSelect()
00980 {
00981    // TODO: Comment me
00982    if (fSelectedCodeIndex.empty())
00983       SelectCode(NULL, NULL, TMemStat::kOR);
00984 
00985    if (fSelectedStackIndex.empty())
00986       SelectStack(TMemStat::kOR);
00987 }
00988 
00989 //______________________________________________________________________________
00990 void TMemStat::Report(Option_t* option)
00991 {
00992    // Report function
00993    // Supported options:
00994    //
00995    // order     : 0 - increasing 1 - decreasing
00996    // sortstat  : 0 - TotalAllocCount 1 -  TotalAlocSize  2 - AllocCount 3 - AllocSize
00997    // sortstamp : 0 - Current 1 -  MaxSize  2 - MaxCount
00998    // sortdeep  : (0-inf) number of info to print
00999    // stackdeep : (0-inf) deepness of stack
01000    // Example   : order 0 sortstat 3 sortstamp 0 sortdeep 10 stackdeep 5 maxlength 50
01001 
01002    ProcessOption(option);
01003 
01004    TString opt(option);
01005    opt.ToLower();
01006    if (opt.Contains("?"))
01007       return;
01008 
01009    RefreshSelect();
01010 
01011    if (!(opt.Contains("code"))) {
01012       SortStack(fSortStat, fSortStamp);
01013       PrintStack(fSortDeep, fStackDeep);
01014    } else {
01015       SortCode(fSortStat, fSortStamp);
01016       PrintCode(fSortDeep);
01017    }
01018 }
01019 
01020 //______________________________________________________________________________
01021 void TMemStat::ResetSelection()
01022 {
01023    // reset all selections
01024 
01025    fSelectedCodeIndex.clear();
01026    fSelectedStackIndex.clear();
01027 
01028    delete fSelectedCodeBitmap;
01029    fSelectedCodeBitmap = NULL;
01030    delete fSelectedStackBitmap;
01031    fSelectedStackBitmap = NULL;
01032    delete fStackSummary;
01033    fStackSummary = NULL;
01034 }
01035 
01036 //______________________________________________________________________________
01037 void TMemStat::SetAutoStamp(Int_t autoStampSize, Int_t autoStampAlloc)
01038 {
01039    // Change default values of the auto stamping
01040    //   autoStampSize  [in] - size of invoking STAMPs
01041    //   autoStampAlloc [in] - a number of allocations
01042 
01043    if (autoStampSize > 0)
01044       TMemStatManager::GetInstance()->SetAutoStamp(autoStampSize, autoStampAlloc, 10000);
01045 }
01046 
01047 //______________________________________________________________________________
01048 void TMemStat::SetCurrentStamp(const char *stampName)
01049 {
01050    // Getvalues for iven stamp
01051 
01052    GetStampList();
01053 
01054    const Int_t entry = find_string(*fStampArray, stampName);
01055    GetMemStat(0, entry);
01056 }
01057 
01058 //______________________________________________________________________________
01059 void TMemStat::SetCurrentStamp(const TObjString &stampName)
01060 {
01061    // TODO: Comment me
01062    SetCurrentStamp(stampName.GetString());
01063 }
01064 
01065 //______________________________________________________________________________
01066 void TMemStat::SelectCode(const char *contlib, const char *contfunction, OperType oType)
01067 {
01068    // select code with given mask
01069    // contlib       - select only code containing contlib in library path
01070    // contfunction  - select only code with function name containing contfunction
01071    // oType         - logical operation - AND and Or is supported
01072    // By default all code is enabled
01073 
01074    if (!fManager) {
01075       Error("SelectCode", "MemStat Manager is the NULL object.");
01076       return;
01077    }
01078 
01079    const size_t entries = fManager->fCodeInfoArray.size();
01080 
01081    fSelectedCodeIndex.clear();
01082 
01083    if (!fSelectedCodeBitmap) {
01084       fSelectedCodeBitmap = new TBits(entries);
01085       for (UInt_t i = 0; i < entries; ++i)
01086          fSelectedCodeBitmap->SetBitNumber(i, kFALSE);
01087    }
01088 
01089    switch (oType) {
01090    case kOR:
01091       for (UInt_t i = 0; i < entries; ++i) {
01092          if (fSelectedCodeBitmap->TestBitNumber(i))
01093             continue;
01094          const TMemStatCodeInfo &info = fManager->fCodeInfoArray[i];
01095          if (contlib && (!(info.fLib.Contains(contlib))))
01096             continue;
01097          if (contfunction && (!(info.fFunction.Contains(contfunction))))
01098             continue;
01099          if (info.fFunction.Contains("TObject::operator new"))
01100             continue;
01101          fSelectedCodeBitmap->SetBitNumber(i);
01102       }
01103       break;
01104    case kAND:
01105       for (UInt_t i = 0; i < entries; i++) {
01106          if (!(fSelectedCodeBitmap->TestBitNumber(i)))
01107             continue;
01108          const TMemStatCodeInfo&info = fManager->fCodeInfoArray[i];
01109          fSelectedCodeBitmap->SetBitNumber(i, kFALSE);
01110          if (contlib && (!(info.fLib.Contains(contlib))))
01111             continue;
01112          if (contfunction && (!(info.fFunction.Contains(contfunction))))
01113             continue;
01114          if (info.fFunction.Contains("TObject::operator new"))
01115             continue;
01116          fSelectedCodeBitmap->SetBitNumber(i, kTRUE);
01117       }
01118       break;
01119    case kNOT:
01120       break;
01121    }
01122 
01123    MakeCodeArray();
01124 }
01125 
01126 //______________________________________________________________________________
01127 void TMemStat::SelectStack(OperType oType)
01128 {
01129    // select stack containing the selected code
01130    // oType - And and OR is supported (AND, OR in respect with previous selection)
01131 
01132    if (!fSelectedCodeBitmap || !fManager)
01133       return;
01134 
01135    const size_t entries = fManager->fStackVector.size();
01136 
01137    fSelectedStackIndex.clear();
01138 
01139    if (!fSelectedStackBitmap) {
01140       fSelectedStackBitmap = new TBits(entries);
01141       for (UInt_t i = 0; i < entries; ++i)
01142          fSelectedStackBitmap->SetBitNumber(i, kFALSE);
01143    }
01144 
01145    switch (oType) {
01146    case kOR:
01147       for (UInt_t i = 0; i < entries; ++i) {
01148          if (fSelectedStackBitmap->TestBitNumber(i))
01149             continue;
01150          const TMemStatStackInfo &info = fManager->fStackVector[i];
01151          for (UInt_t icode = 0; icode < info.fSize; ++icode) {
01152             if (fSelectedCodeBitmap->TestBitNumber(info.fSymbolIndexes[icode])) {
01153                fSelectedStackBitmap->SetBitNumber(i, kTRUE);
01154             }
01155          }
01156       }
01157       break;
01158    case kAND:
01159       for (UInt_t i = 0; i < entries; ++i) {
01160          if (!(fSelectedStackBitmap->TestBitNumber(i)))
01161             continue;
01162          const TMemStatStackInfo &info = fManager->fStackVector[i];
01163          fSelectedStackBitmap->SetBitNumber(i, kFALSE);
01164          for (UInt_t icode = 0; icode < info.fSize; ++icode) {
01165             if (fSelectedCodeBitmap->TestBitNumber(info.fSymbolIndexes[icode])) {
01166                fSelectedStackBitmap->SetBitNumber(i, kTRUE);
01167             }
01168          }
01169       }
01170       break;
01171    case kNOT:
01172       break;
01173    }
01174 
01175    MakeStackArray();
01176 }
01177 
01178 //______________________________________________________________________________
01179 void TMemStat::SortCode(StatType sortType, StampType stampType)
01180 {
01181    // sort code according statistical criteria
01182    // sortType
01183    // stampType
01184 
01185    if (fSelectedCodeIndex.empty() || !fManager)
01186       return;
01187 
01188    const Int_t size = fSelectedCodeIndex.size();
01189    Long64Vector_t values(size);
01190    TArrayI indexes(size);
01191 
01192    const size_t entries = fManager->fCodeInfoArray.size();
01193    Int_t iselected = 0;
01194    for (UInt_t icode = 0; icode < entries; ++icode) {
01195       if (!(fSelectedCodeBitmap->TestBitNumber(icode)))
01196          continue;
01197       TMemStatInfoStamp * info = 0;
01198       switch (stampType) {
01199       case kCurrent:
01200          info = &(fManager->fCodeInfoArray[icode].fCurrentStamp);
01201          break;
01202       case kMaxSize:
01203          info = &(fManager->fCodeInfoArray[icode].fMaxStampSize);
01204          break;
01205       case kMaxCount:
01206          info = &(fManager->fCodeInfoArray[icode].fMaxStamp);
01207          break;
01208       }
01209 
01210       if (!info)
01211          break;
01212 
01213       indexes[iselected] = icode;
01214 
01215       switch (sortType) {
01216       case kTotalAllocCount:
01217          values[iselected] = info->fTotalAllocCount;
01218          break;
01219       case kAllocCount:
01220          values[iselected] = info->fAllocCount;
01221          break;
01222       case kTotalAllocSize:
01223          values[iselected] = info->fTotalAllocSize;
01224          break;
01225       case kAllocSize:
01226          values[iselected] = info->fAllocSize;
01227          break;
01228       case kUndef:
01229          break;
01230       }
01231 
01232       ++iselected;
01233    }
01234 
01235    TArrayI sortIndexes(size);
01236    TMath::Sort(iselected, &values[0], &sortIndexes[0], fOrder);
01237 
01238    fSelectedCodeIndex.clear();
01239    fSelectedCodeIndex.reserve(iselected);
01240    for (Int_t i = 0; i < iselected; ++i)
01241       fSelectedCodeIndex.push_back(indexes[sortIndexes[i]]);
01242 }
01243 
01244 //______________________________________________________________________________
01245 void TMemStat::SortStack(StatType sortType, StampType stampType)
01246 {
01247    // sort code according statistical criteria
01248    // sortType
01249    // stampType
01250 
01251    if (!fSelectedCodeBitmap || !fManager)
01252       return;
01253 
01254    const size_t entries = fManager->fStackVector.size();
01255    Long64Vector_t values(entries);
01256    TArrayI indexes(entries);
01257 
01258    UInt_t iselected = 0;
01259    for (UInt_t istack = 0; istack < entries; ++istack) {
01260       if (!(fSelectedStackBitmap->TestBitNumber(istack)))
01261          continue;
01262       TMemStatInfoStamp * info(NULL);
01263       switch (stampType) {
01264       case kCurrent:
01265          info = &(fManager->fStackVector[istack].fCurrentStamp);
01266          break;
01267       case kMaxSize:
01268          info = &(fManager->fStackVector[istack].fMaxStampSize);
01269          break;
01270       case kMaxCount:
01271          info = &(fManager->fStackVector[istack].fMaxStamp);
01272          break;
01273       }
01274 
01275       indexes[iselected] = istack;
01276 
01277       switch (sortType) {
01278       case kTotalAllocCount:
01279          values[iselected] = info->fTotalAllocCount;
01280          break;
01281       case kAllocCount:
01282          values[iselected] = info->fAllocCount;
01283          break;
01284       case kTotalAllocSize:
01285          values[iselected] = info->fTotalAllocSize;
01286          break;
01287       case kAllocSize:
01288          values[iselected] = info->fAllocSize;
01289          break;
01290       case kUndef:
01291          break;
01292       }
01293       if (values[iselected] == 0) continue;
01294       ++iselected;
01295    }
01296    TArrayI  sortIndexes(entries);
01297    TMath::Sort(static_cast<Int_t>(iselected), &values[0], &sortIndexes[0], fOrder);
01298    const Int_t sizeOut = TMath::Min(fSortDeep, iselected);
01299    fSelectedStackIndex.clear();
01300    fSelectedStackIndex.reserve(sizeOut);
01301    if (fOrder) {
01302       for (Int_t i = 0; i < sizeOut; ++i)
01303          fSelectedStackIndex.push_back(indexes[sortIndexes[i]]);
01304    } else {
01305       const Int_t first = (iselected < fSortDeep) ? 0 : iselected - fSortDeep;
01306       for (UInt_t i = first; i < (first + fSortDeep) && i < iselected; ++i) {
01307          const UInt_t indexS = sortIndexes[i];
01308          if (indexS >= entries) {
01309             cerr << "Error 0 \n";
01310             continue;
01311          }
01312          if (static_cast<size_t>(indexes[indexS]) >= entries) {
01313             cerr << "Error 1 \n";
01314             continue;
01315          }
01316          const Long64_t value = values[indexS];
01317          if (0 == value) {
01318             cerr << "Error 2\n";
01319             continue;
01320          }
01321          fSelectedStackIndex.push_back(indexes[indexS]);
01322       }
01323    }
01324 }

Generated on Tue Jul 5 14:44:00 2011 for ROOT_528-00b_version by  doxygen 1.5.1