00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 #include <map>
00097 #include <vector>
00098 #include <iostream>
00099
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
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
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 _GET_TO_STECK;
00187
00188
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)
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
00202 fIsActive = kTRUE;
00203 }
00204 else if ( opt.find("read") != string::npos)
00205 {
00206
00207 GetMemStat("memstat.root", -1);
00208
00209
00210 fDisablePrintLib.SetOwner();
00211 fDisablePrintLib.AddLast(new TObjString("libRIO"));
00212 fDisablePrintCode.SetOwner();
00213 fDisablePrintCode.AddLast(new TObjString("TClass::Streamer"));
00214
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
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
00242
00243 TMemStatManager::GetInstance()->AddStamps(stampName);
00244 }
00245
00246
00247 Int_t TMemStat::DistancetoPrimitive(Int_t px, Int_t py)
00248 {
00249
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
00268
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
00353
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 , Int_t , Int_t )
00384 {
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 }
00404
00405
00406 void TMemStat::GetFillSelection(Selection_t *_Container, ESelection _Selection) const
00407 {
00408
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
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
00440
00441
00442
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
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
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
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
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
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
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
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
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 )
00715 {
00716
00717
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
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
00770
00771
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
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
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825 }
00826
00827
00828 void TMemStat::Paint(Option_t * )
00829 {
00830
00831 }
00832
00833
00834 void TMemStat::PrintCode(Int_t nentries) const
00835 {
00836
00837
00838
00839
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
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
00865
00866
00867
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
00887
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
00915
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
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
00993
00994
00995
00996
00997
00998
00999
01000
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
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
01040
01041
01042
01043 if (autoStampSize > 0)
01044 TMemStatManager::GetInstance()->SetAutoStamp(autoStampSize, autoStampAlloc, 10000);
01045 }
01046
01047
01048 void TMemStat::SetCurrentStamp(const char *stampName)
01049 {
01050
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
01062 SetCurrentStamp(stampName.GetString());
01063 }
01064
01065
01066 void TMemStat::SelectCode(const char *contlib, const char *contfunction, OperType oType)
01067 {
01068
01069
01070
01071
01072
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
01130
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
01182
01183
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
01248
01249
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 }