#include <map>
#include <vector>
#include <iostream>
#include "TTree.h"
#include "TMath.h"
#include "TArrayI.h"
#include "TBits.h"
#include "TDirectory.h"
#include "TAxis.h"
#include "TGraph.h"
#include "TLegend.h"
#include "TText.h"
#include "THStack.h"
#include "TSystem.h"
#include "TMemStat.h"
#include "TMemStatInfo.h"
#include "TMemStatManager.h"
#include "TMemStatHelpers.h"
ClassImp(TMemStat)
using namespace std;
using namespace Memstat;
typedef vector<Long64_t> Long64Vector_t;
typedef vector<Double_t> DoubleVector_t;
_INIT_TOP_STECK;
struct SFillSelection: public binary_function<
         TMemStatManager::CodeInfoContainer_t::value_type,
         TMemStat::ESelection,
         TMemStat::Selection_t::value_type>
{
   TMemStat::Selection_t::value_type operator() (
      const TMemStatManager::CodeInfoContainer_t::value_type &_code_info,
      TMemStat::ESelection _Selection ) const
   {
      switch ( _Selection )
      {
      case TMemStat::kFunction:
         return _code_info.fFunction.Data();
      case TMemStat::kLibrary:
         
         return gSystem->BaseName(_code_info.fLib.Data());
      default:
         return string();
      }
   }
};
TMemStat::TMemStat(Option_t* option):
      TObject(),
      fSortStat(kAllocSize),
      fSortStamp(kCurrent),
      fSortDeep(10),
      fStackDeep(20),
      fMaxStringLength(50),
      fSelected(0),
      fIsActive(kFALSE),
      fOrder(kFALSE),
      fSelectedCodeBitmap(NULL),
      fSelectedStackBitmap(NULL),
      fStampArray(NULL),
      fArray(NULL),
      fArrayGraphics(NULL),
      fTree(NULL),
      fTreeSys(NULL),
      fStackSummary(NULL),
      fManager(NULL)
{
   
   
   
   
   
   
   
   
   
   _GET_TO_STECK;
   
   TDirectory::TContext context(gDirectory);
   string opt(option);
   transform( opt.begin(), opt.end(), opt.begin(),
              Memstat::ToLower_t() );
   if ( opt.find("new") != string::npos) 
   {
      SetAutoStamp();
      const Bool_t useBuildin = (opt.find("gnubuildin") != string::npos)? kTRUE: kFALSE;
      TMemStatManager::GetInstance()->SetUseGNUBuildinBacktrace(useBuildin);
      TMemStatManager::GetInstance()->Enable();
      
      fIsActive = kTRUE;
   }
   else if ( opt.find("read") != string::npos) 
   {
      
      GetMemStat("memstat.root", -1);
      
      fDisablePrintLib.SetOwner();
      fDisablePrintLib.AddLast(new TObjString("libRIO"));
      fDisablePrintCode.SetOwner();
      fDisablePrintCode.AddLast(new TObjString("TClass::Streamer"));
      
      ProcessOption("order 0 sortstat 3 sortstamp 0 sortdeep 30 stackdeep 15 maxlength 50");
   }
   else
   {
      Error("TMemStat", "Invalid option");
   }
}
TMemStat::~TMemStat()
{
   
   if (fIsActive) {
      TMemStatManager::GetInstance()->Disable();
      TMemStatManager::GetInstance()->Close();
   }
   delete fStackSummary;
   delete fSelectedCodeBitmap;
   delete fSelectedStackBitmap;
}
void TMemStat::AddStamp(const char*stampName)
{
   
   TMemStatManager::GetInstance()->AddStamps(stampName);
}
void TMemStat::Draw(Option_t * )
{
   
   
   
   
}
void TMemStat::GetFillSelection(Selection_t *_Container, ESelection _Selection) const
{
   
   if ( !_Container || !fManager)
      return;
   transform( fManager->fCodeInfoArray.begin(),
              fManager->fCodeInfoArray.end(),
              inserter(*_Container, _Container->begin()),
              bind2nd(SFillSelection(), _Selection) );
}
TObjArray* TMemStat::GetStampList()
{
   
   if (fStampArray)
      return fStampArray;
   if (!fTreeSys)
      return NULL;
   TObjString str;
   TObjString *pstr = &str;
   fStampArray = new TObjArray;
   fTreeSys->SetBranchAddress("StampName.", &pstr);
   for (Int_t i = 0; i < fTreeSys->GetEntries(); ++i) {
      fTreeSys->GetEntry(i);
      fStampArray->AddLast(str.Clone());
   }
   return fStampArray;
}
void TMemStat::MakeReport(const char * lib, const char *fun, Option_t* option, const char *fileName)
{
   
   
   SelectCode(NULL, NULL, TMemStat::kOR);
   SelectStack(TMemStat::kOR);
   
   SelectCode(lib, fun, TMemStat::kAND);
   SelectStack(TMemStat::kAND);
   if (option)
      ProcessOption(option);
   SortCode(fSortStat, fSortStamp);
   SortStack(fSortStat, fSortStamp);
   
   if (strlen(fileName) > 0)
      gSystem->RedirectOutput(fileName, "w");
   Report();
   if (strlen(fileName) > 0)
      gSystem->RedirectOutput(0);
}
void TMemStat::MakeHisMemoryStamp(Int_t )
{
   
   
   const Int_t entries = fTreeSys->Draw("Mem3", "Mem3>0", "");
   DoubleVector_t diff(entries - 1);
   for (Int_t i = 0; i < entries - 1; ++i) {
      diff[i] = fTreeSys->GetV1()[i+1] - fTreeSys->GetV1()[i];
   }
   IntVector_t indexes(entries - 1);
   TMath::Sort(entries - 1, &diff[0], &indexes[0], kFALSE);
}
void TMemStat::MakeHisMemoryTime()
{
   
   fTreeSys->Draw("Mem3:StampTime.fSec>>hhh", "", "goff*");
   if (!gROOT->FindObject("hhh"))
      return ;
   TH1* his3 = (TH1*)gROOT->FindObject("hhh")->Clone("Virtual Memory");
   his3->SetDirectory(0);
   delete gROOT->FindObject("hhh");
   fTreeSys->Draw("Mem2:StampTime.fSec>>hhh", "", "goff*");
   if (!gROOT->FindObject("hhh"))
      return ;
   TH1* his2 = (TH1*)gROOT->FindObject("hhh")->Clone("Residual Memory");
   his2->SetDirectory(0);
   delete gROOT->FindObject("hhh");
   fTreeSys->Draw("CurrentStamp.fAllocSize/1000000.:StampTime.fSec>>hhh", "", "goff*");
   if (!gROOT->FindObject("hhh"))
      return ;
   TH1* hism = (TH1*)gROOT->FindObject("hhh")->Clone("Allocated Memory");
   hism->SetDirectory(0);
   delete gROOT->FindObject("hhh");
   his3->GetXaxis()->SetTimeDisplay(1);
   his3->SetMarkerColor(2);
   his2->SetMarkerColor(3);
   hism->SetMarkerColor(4);
   his3->Draw();
   his2->Draw("same");
   hism->Draw("same");
}
void TMemStat::Paint(Option_t * )
{
   
}
void TMemStat::PrintCode(Int_t nentries) const
{
   
   
   
   
   if (fSelectedCodeIndex.empty() || !fManager)
      return;
   UIntVector_t::const_iterator iter = max((fSelectedCodeIndex.end() - nentries), fSelectedCodeIndex.begin());
   UIntVector_t::const_iterator iter_end = fSelectedCodeIndex.end();
   for (; iter != iter_end; ++iter)
      fManager->fCodeInfoArray[*iter].Print();
}
void TMemStat::PrintCodeWithID(UInt_t id) const
{
   
   if (!fManager)
      return;
   if (id > fManager->fCodeInfoArray.size())
      return;
   fManager->fCodeInfoArray[id].Print();
}
void TMemStat::PrintStack(Int_t nentries, UInt_t deep) const
{
   
   
   
   
   if (fSelectedStackIndex.empty())
      return;
   UIntVector_t::const_iterator iter = max((fSelectedStackIndex.end() - nentries), fSelectedStackIndex.begin());
   UIntVector_t::const_iterator iter_end = fSelectedStackIndex.end();
   for (; iter != iter_end; ++iter)
      PrintStackWithID(*iter, deep);
   cout << "Summary for selected:" << endl;
   ios::fmtflags old_flags(cout.flags(ios::left));
   fStackSummary->Print();
   cout.flags(old_flags);
}
void TMemStat::PrintStackWithID(UInt_t _id, UInt_t _deep) const
{
   
   
   if (!fManager)
      return;
   _deep = !_deep ? fStackDeep : _deep;
   const TMemStatStackInfo &infoStack = fManager->fStackVector[_id];
   cout << infoStack << endl;
   ios::fmtflags old_flags(cout.flags(ios::left));
   for (UInt_t icode = 0, counter = 0; icode < infoStack.fSize; ++icode) {
      const TMemStatCodeInfo &infoCode(fManager->fCodeInfoArray[infoStack.fSymbolIndexes[icode]]);
      if (!EnabledCode(infoCode))
         continue;
      cout
      << setw(5) << icode
      << infoCode << endl;
      ++counter;
      if (counter >= _deep)
         break;
   }
   cout.flags(old_flags);
}
void TMemStat::Report(Option_t* option)
{
   
   
   
   
   
   
   
   
   
   ProcessOption(option);
   TString opt(option);
   opt.ToLower();
   if (opt.Contains("?"))
      return;
   RefreshSelect();
   if (!(opt.Contains("code"))) {
      SortStack(fSortStat, fSortStamp);
      PrintStack(fSortDeep, fStackDeep);
   } else {
      SortCode(fSortStat, fSortStamp);
      PrintCode(fSortDeep);
   }
}
void TMemStat::ResetSelection()
{
   
   fSelectedCodeIndex.clear();
   fSelectedStackIndex.clear();
   delete fSelectedCodeBitmap;
   fSelectedCodeBitmap = NULL;
   delete fSelectedStackBitmap;
   fSelectedStackBitmap = NULL;
   delete fStackSummary;
   fStackSummary = NULL;
}
void TMemStat::SetAutoStamp(Int_t autoStampSize, Int_t autoStampAlloc)
{
   
   
   
   if (autoStampSize > 0)
      TMemStatManager::GetInstance()->SetAutoStamp(autoStampSize, autoStampAlloc, 10000);
}
void TMemStat::SetCurrentStamp(const char *stampName)
{
   
   GetStampList();
   const Int_t entry = find_string(*fStampArray, stampName);
   GetMemStat(0, entry);
}
void TMemStat::SetCurrentStamp(const TObjString &stampName)
{
   
   SetCurrentStamp(stampName.GetString());
}
void TMemStat::SelectCode(const char *contlib, const char *contfunction, OperType oType)
{
   
   
   
   
   
   if (!fManager) {
      Error("SelectCode", "MemStat Manager is the NULL object.");
      return;
   }
   const size_t entries = fManager->fCodeInfoArray.size();
   fSelectedCodeIndex.clear();
   if (!fSelectedCodeBitmap) {
      fSelectedCodeBitmap = new TBits(entries);
      for (UInt_t i = 0; i < entries; ++i)
         fSelectedCodeBitmap->SetBitNumber(i, kFALSE);
   }
   switch (oType) {
   case kOR:
      for (UInt_t i = 0; i < entries; ++i) {
         if (fSelectedCodeBitmap->TestBitNumber(i))
            continue;
         const TMemStatCodeInfo &info = fManager->fCodeInfoArray[i];
         if (contlib && (!(info.fLib.Contains(contlib))))
            continue;
         if (contfunction && (!(info.fFunction.Contains(contfunction))))
            continue;
         if (info.fFunction.Contains("TObject::operator new"))
            continue;
         fSelectedCodeBitmap->SetBitNumber(i);
      }
      break;
   case kAND:
      for (UInt_t i = 0; i < entries; i++) {
         if (!(fSelectedCodeBitmap->TestBitNumber(i)))
            continue;
         const TMemStatCodeInfo&info = fManager->fCodeInfoArray[i];
         fSelectedCodeBitmap->SetBitNumber(i, kFALSE);
         if (contlib && (!(info.fLib.Contains(contlib))))
            continue;
         if (contfunction && (!(info.fFunction.Contains(contfunction))))
            continue;
         if (info.fFunction.Contains("TObject::operator new"))
            continue;
         fSelectedCodeBitmap->SetBitNumber(i, kTRUE);
      }
      break;
   case kNOT:
      break;
   }
   MakeCodeArray();
}
void TMemStat::SelectStack(OperType oType)
{
   
   
   if (!fSelectedCodeBitmap || !fManager)
      return;
   const size_t entries = fManager->fStackVector.size();
   fSelectedStackIndex.clear();
   if (!fSelectedStackBitmap) {
      fSelectedStackBitmap = new TBits(entries);
      for (UInt_t i = 0; i < entries; ++i)
         fSelectedStackBitmap->SetBitNumber(i, kFALSE);
   }
   switch (oType) {
   case kOR:
      for (UInt_t i = 0; i < entries; ++i) {
         if (fSelectedStackBitmap->TestBitNumber(i))
            continue;
         const TMemStatStackInfo &info = fManager->fStackVector[i];
         for (UInt_t icode = 0; icode < info.fSize; ++icode) {
            if (fSelectedCodeBitmap->TestBitNumber(info.fSymbolIndexes[icode])) {
               fSelectedStackBitmap->SetBitNumber(i, kTRUE);
            }
         }
      }
      break;
   case kAND:
      for (UInt_t i = 0; i < entries; ++i) {
         if (!(fSelectedStackBitmap->TestBitNumber(i)))
            continue;
         const TMemStatStackInfo &info = fManager->fStackVector[i];
         fSelectedStackBitmap->SetBitNumber(i, kFALSE);
         for (UInt_t icode = 0; icode < info.fSize; ++icode) {
            if (fSelectedCodeBitmap->TestBitNumber(info.fSymbolIndexes[icode])) {
               fSelectedStackBitmap->SetBitNumber(i, kTRUE);
            }
         }
      }
      break;
   case kNOT:
      break;
   }
   MakeStackArray();
}
void TMemStat::SortCode(StatType sortType, StampType stampType)
{
   
   
   
   if (fSelectedCodeIndex.empty() || !fManager)
      return;
   const Int_t size = fSelectedCodeIndex.size();
   Long64Vector_t values(size);
   TArrayI indexes(size);
   const size_t entries = fManager->fCodeInfoArray.size();
   Int_t iselected = 0;
   for (UInt_t icode = 0; icode < entries; ++icode) {
      if (!(fSelectedCodeBitmap->TestBitNumber(icode)))
         continue;
      TMemStatInfoStamp * info = 0;
      switch (stampType) {
      case kCurrent:
         info = &(fManager->fCodeInfoArray[icode].fCurrentStamp);
         break;
      case kMaxSize:
         info = &(fManager->fCodeInfoArray[icode].fMaxStampSize);
         break;
      case kMaxCount:
         info = &(fManager->fCodeInfoArray[icode].fMaxStamp);
         break;
      }
      if (!info)
         break;
      indexes[iselected] = icode;
      switch (sortType) {
      case kTotalAllocCount:
         values[iselected] = info->fTotalAllocCount;
         break;
      case kAllocCount:
         values[iselected] = info->fAllocCount;
         break;
      case kTotalAllocSize:
         values[iselected] = info->fTotalAllocSize;
         break;
      case kAllocSize:
         values[iselected] = info->fAllocSize;
         break;
      case kUndef:
         break;
      }
      ++iselected;
   }
   TArrayI sortIndexes(size);
   TMath::Sort(iselected, &values[0], &sortIndexes[0], fOrder);
   fSelectedCodeIndex.clear();
   fSelectedCodeIndex.reserve(iselected);
   for (Int_t i = 0; i < iselected; ++i)
      fSelectedCodeIndex.push_back(indexes[sortIndexes[i]]);
}
void TMemStat::SortStack(StatType sortType, StampType stampType)
{
   
   
   
   if (!fSelectedCodeBitmap || !fManager)
      return;
   const size_t entries = fManager->fStackVector.size();
   Long64Vector_t values(entries);
   TArrayI indexes(entries);
   UInt_t iselected = 0;
   for (UInt_t istack = 0; istack < entries; ++istack) {
      if (!(fSelectedStackBitmap->TestBitNumber(istack)))
         continue;
      TMemStatInfoStamp * info(NULL);
      switch (stampType) {
      case kCurrent:
         info = &(fManager->fStackVector[istack].fCurrentStamp);
         break;
      case kMaxSize:
         info = &(fManager->fStackVector[istack].fMaxStampSize);
         break;
      case kMaxCount:
         info = &(fManager->fStackVector[istack].fMaxStamp);
         break;
      }
      indexes[iselected] = istack;
      switch (sortType) {
      case kTotalAllocCount:
         values[iselected] = info->fTotalAllocCount;
         break;
      case kAllocCount:
         values[iselected] = info->fAllocCount;
         break;
      case kTotalAllocSize:
         values[iselected] = info->fTotalAllocSize;
         break;
      case kAllocSize:
         values[iselected] = info->fAllocSize;
         break;
      case kUndef:
         break;
      }
      if (values[iselected] == 0) continue;
      ++iselected;
   }
   TArrayI  sortIndexes(entries);
   TMath::Sort(iselected, &values[0], &sortIndexes[0], fOrder);
   const Int_t sizeOut = TMath::Min(fSortDeep, iselected);
   fSelectedStackIndex.clear();
   fSelectedStackIndex.reserve(sizeOut);
   if (fOrder) {
      for (Int_t i = 0; i < sizeOut; ++i)
         fSelectedStackIndex.push_back(indexes[sortIndexes[i]]);
   } else {
      const Int_t first = (iselected < fSortDeep) ? 0 : iselected - fSortDeep;
      for (UInt_t i = first; i < (first + fSortDeep) && i < iselected; ++i) {
         const UInt_t indexS = sortIndexes[i];
         if (indexS >= entries) {
            cerr << "Error 0 \n";
            continue;
         }
         if (static_cast<size_t>(indexes[indexS]) >= entries) {
            cerr << "Error 1 \n";
            continue;
         }
         const Long64_t value = values[indexS];
         if (0 == value) {
            cerr << "Error 2\n";
            continue;
         }
         fSelectedStackIndex.push_back(indexes[indexS]);
      }
   }
}
Int_t TMemStat::DistancetoPrimitive(Int_t , Int_t )
{
   
   
   
   return -1;
}
Bool_t TMemStat::GetMemStat(const char * fname, Int_t entry)
{
   
   if (fname != 0) {
      fFile.reset(TFile::Open(fname));
      if (!fFile.get() || fFile->IsZombie())
         return kFALSE;
      fTree = dynamic_cast<TTree*>(fFile->Get("MemStat"));
      if (!fTree)
         return kFALSE;
      fTreeSys = dynamic_cast<TTree*>(fFile->Get("MemSys"));
      if (!fTreeSys)
         return kFALSE;
   }
   TMemStatManager *man(NULL);
   
   
   
   
   fTree->ResetBranchAddresses();
   fTree->SetBranchAddress("Manager", &man);
   if ( (entry < 0) || (entry >= fTree->GetEntries()) )
      entry = fTree->GetEntries() - 1;
   fTree->GetEntry(entry);
   fManager = man;
   return kTRUE;
}
Bool_t TMemStat::EnabledCode(const TMemStatCodeInfo &info) const
{
   
   
   if (info.fLib.Contains("libMemStat.so"))
      return kFALSE;
   if (info.fFunction.Contains("operator new"))
      return kFALSE;
   if (info.fFunction.Contains("TMethodCall::Execute"))
      return kFALSE;
   if (info.fFunction.Contains("Cint::G__CallFunc::Exec"))
      return kFALSE;
   if (info.fFunction.Contains("Cint::G__ExceptionWrapper"))
      return kFALSE;
   if (info.fFunction.Sizeof() <= 1)
      return kFALSE;
   for (Int_t i = 0; i < fDisablePrintLib.GetEntries(); ++i) {
      TObjString * str = (TObjString*)fDisablePrintLib.At(i);
      if (str && info.fLib.Contains(str->String().Data()))
         return kFALSE;
   }
   for (Int_t i = 0; i < fDisablePrintCode.GetEntries(); ++i) {
      TObjString * str = (TObjString*)fDisablePrintCode.At(i);
      if (str && info.fFunction.Contains(str->String().Data()))
         return kFALSE;
   }
   return kTRUE;
}
void TMemStat::ExecuteEvent(Int_t , Int_t , Int_t )
{
   
   
   
}
void TMemStat::MakeCodeArray()
{
   
   if (!fManager)
      return;
   Int_t nselected = 0;
   size_t csize = fManager->fCodeInfoArray.size();
   for (UInt_t i = 0; i < csize; ++i)
      if (fSelectedCodeBitmap->TestBitNumber(i))
         ++nselected;
   fSelectedCodeIndex.clear();
   fSelectedCodeIndex.reserve(nselected);
   for (UInt_t i = 0; i < csize; ++i) {
      if (fSelectedCodeBitmap->TestBitNumber(i))
         fSelectedCodeIndex.push_back(i);
   }
}
void TMemStat::MakeStackArray()
{
   
   if (!fManager)
      return;
   delete fStackSummary;
   fStackSummary = new TMemStatInfoStamp();
   fSelectedStackIndex.clear();
   const size_t csize = fManager->fStackVector.size();
   for (size_t i = 0; i < csize; ++i) {
      if (fSelectedStackBitmap->TestBitNumber(i)) {
         fSelectedStackIndex.push_back(i);
         const TMemStatStackInfo &info = fManager->fStackVector[i];
         fStackSummary->fTotalAllocCount += info.fCurrentStamp.fTotalAllocCount;
         fStackSummary->fTotalAllocSize += info.fCurrentStamp.fTotalAllocSize;
         fStackSummary->fAllocCount += info.fCurrentStamp.fAllocCount;
         fStackSummary->fAllocSize += info.fCurrentStamp.fAllocSize;
      }
   }
}
TObjArray *TMemStat::MakeGraphCode(StatType statType, Int_t nentries)
{
   
   if (fArray) {
      fArray->Delete();
      delete fArray;
   }
   fArray  = new TObjArray(nentries);
   fArrayIndexes.clear();
   fArrayIndexes.resize(nentries);
   Int_t count = 0;
   Double_t xmin = 0, xmax = 0, ymin = 0, ymax = 0;
   Int_t first = TMath::Max(static_cast<Int_t>(fSelectedCodeIndex.size()) - nentries, 0);
   Double_t cxmax, cymax;
   for (Int_t i = fSelectedCodeIndex.size() - 1; i > first; --i) {
      TGraph * gr = MakeGraph(statType, fSelectedCodeIndex[i], TMemStatInfoStamp::kCode, cxmax, cymax);
      if (!gr)
         continue;
      TMemStatCodeInfo  &cinfo =  fManager->fCodeInfoArray[fSelectedCodeIndex[i]];
      if (cinfo.fFunction.Length() > 0) {
         TString str(cinfo.fFunction);
         if ((UInt_t)(str.Length()) > fMaxStringLength)
            str.Resize(fMaxStringLength);
         gr->SetName(str);
      }
      ++count;
      gr->SetLineColor(count % 5 + 1);
      fArrayIndexes[fArray->GetEntries()] = -fSelectedCodeIndex[i];
      fArray->AddLast(gr);
      if (xmin == xmax) {
         xmin = gr->GetXaxis()->GetXmin();
         xmax = cxmax;
         ymin = gr->GetYaxis()->GetXmin();
         ymax = cymax;
      } else {
         xmin = min(xmin, gr->GetXaxis()->GetXmin());
         xmax = max(xmax, cxmax);
         ymin = min(ymin, gr->GetYaxis()->GetXmin());
         ymax = max(ymax, cymax);
      }
   }
   for (Int_t i = 0;i < fArray->GetEntries(); ++i) {
      TGraph * gr = (TGraph*)fArray->At(i);
      gr->GetXaxis()->SetLimits(xmin, xmax);
      gr->GetYaxis()->SetLimits(ymin, ymax);
   }
   return fArray;
}
TObjArray *TMemStat::MakeGraphStack(StatType statType, Int_t nentries)
{
   
   if (fArray) {
      fArray->Delete();
      delete fArray;
   }
   fArray = new TObjArray(nentries);
   fArrayIndexes.clear();
   fArrayIndexes.resize(nentries);
   Int_t count = 0;
   Double_t xmin = 0, xmax = 0, ymin = 0, ymax = 0;
   const Int_t first = TMath::Max(static_cast<int>(fSelectedStackIndex.size()) - nentries, 0);
   Double_t cxmax(0);
   Double_t cymax(0);
   for (Int_t i = fSelectedStackIndex.size() - 1; i > first; --i) {
      TGraph * gr = MakeGraph(statType, fSelectedStackIndex[i], TMemStatInfoStamp::kStack, cxmax, cymax);
      if (!gr)
         continue;
      TMemStatStackInfo &infoStack = fManager->fStackVector[(fSelectedStackIndex[i])];
      for (UInt_t icode = 0; icode < infoStack.fSize; icode++) {
         TMemStatCodeInfo &infoCode = fManager->fCodeInfoArray[infoStack.fSymbolIndexes[icode]];
         if (EnabledCode(infoCode)) {
            if (infoCode.fFunction) {
               TString str(infoCode.fFunction);
               if ((UInt_t)(str.Length()) > fMaxStringLength) str.Resize(fMaxStringLength);
               gr->SetName(str);
               gr->SetUniqueID(fSelectedStackIndex[i]);
            }
            break;
         }
      }
      ++count;
      gr->SetLineColor(count % 5 + 1);
      gr->SetMarkerColor(count % 5 + 1);
      gr->SetMarkerStyle(20 + count % 5);
      gr->SetMarkerSize(0.15);
      fArrayIndexes[fArray->GetEntries()] = fSelectedStackIndex[i];
      fArray->AddLast(gr);
      if (xmin == xmax) {
         xmin = gr->GetXaxis()->GetXmin();
         xmax = cxmax;
         ymin = gr->GetYaxis()->GetXmin();
         ymax = cymax;
      } else {
         xmin = min(xmin, gr->GetXaxis()->GetXmin());
         xmax = max(xmax, cxmax);
         ymin = min(ymin, gr->GetYaxis()->GetXmin());
         ymax = max(ymax, cymax);
      }
   }
   for (Int_t i = 0; i < fArray->GetEntries(); ++i) {
      TGraph * gr = (TGraph*)fArray->At(i);
      gr->GetXaxis()->SetLimits(xmin, xmax);
      gr->GetYaxis()->SetLimits(ymin, ymax);
   }
   return fArray;
}
TGraph *TMemStat::MakeGraph(StatType statType, Int_t id, Int_t type, Double_t &xmax, Double_t &ymax)
{
   
   if (!fTree)
      return 0;
   string sWhat;
   string sWhatName;
   switch (statType) {
   case kTotalAllocCount:
      sWhat = "fStampVector.fTotalAllocCount:fStampVector.fStampNumber";
      sWhatName = "TotalAllocCount";
      break;
   case kAllocCount:
      sWhat = "fStampVector.fAllocCount:fStampVector.fStampNumber";
      sWhatName = "AllocCount";
      break;
   case kTotalAllocSize:
      sWhat = "fStampVector.fTotalAllocSize/1000000.:fStampVector.fStampNumber";
      sWhatName = "TotalAllocSize (MBy)";
      break;
   case kAllocSize:
      sWhat = "fStampVector.fAllocSize/1000000.:fStampVector.fStampNumber";
      sWhatName = "AllocSize (MBy)";
      break;
   case kUndef:
      
      break;
   }
   ostringstream ssWhere;
   ssWhere << "fStampVector.fID==" << id << "&&fStampVector.fStampType==" << type;
   const Int_t entries = fTree->Draw(sWhat.c_str(), ssWhere.str().c_str(), "goff");
   if (entries <= 0)
      return 0;
   const Int_t maxStamp = fManager->fStampNumber;
   Float_t *x = new Float_t[maxStamp];
   Float_t *y = new Float_t[maxStamp];
   xmax = 0;
   ymax = 0;
   Float_t last = 0;
   for (Int_t i = 0, counter = 0; i < maxStamp; ++i) {
      x[i] = i;
      y[i] = last;
      if (y[i] > ymax) ymax = y[i];
      if (x[i] > xmax) xmax = x[i];
      if (counter >= entries)
         continue;
      if (fTree->GetV2()[counter] > i) {
         y[i] = last;
      } else {
         y[i] = fTree->GetV1()[counter];
         last = y[i];
         ++counter;
      }
   }
   TGraph * graph  = new TGraph(maxStamp, x, y);
   graph->GetXaxis()->SetTitle("StampNumber");
   graph->GetYaxis()->SetTitle(sWhatName.c_str());
   return graph;
}
void TMemStat::MakeStampsText()
{
   
   
   
   
}
void TMemStat::ProcessOption(Option_t *option)
{
   
   
   TString str(option);
   TString delim(" ");
   TObjArray *tokens = str.Tokenize(delim);
   for (Int_t i = 0; i < tokens->GetEntriesFast() - 1; ++i) {
      TObjString *strTok = (TObjString*)tokens->At(i);
      TObjString *strNum = (i < tokens->GetEntriesFast()) ? (TObjString*)tokens->At(i + 1) : 0;
      if (strNum && strNum->String().IsDigit()) {
         if (strTok->String().Contains("sortstat")) {
            Int_t val = strNum->String().Atoi();
            if (val > 3) {
               Error("SetOption", Form("Invalid value for sortstat %d", val));
               val = 3;
            }
            fSortStat = (TMemStat::StatType)val;
         }
         if (strTok->String().Contains("sortstamp")) {
            Int_t val = strNum->String().Atoi();
            if (val > 2) {
               Error("SetOption", Form("Invalid value for sortstamp %d", val));
               val = 0;
            }
            fSortStamp = (TMemStat::StampType)val;
         }
         if (strTok->String().Contains("order")) {
            Int_t val = strNum->String().Atoi();
            if (val > 1) {
               Error("SetOption", Form("Invalid sorting value", val));
               val = 0;
            }
            fOrder = (val > 0);
         }
         if (strTok->String().Contains("sortdeep")) {
            fSortDeep = strNum->String().Atoi();
         }
         if (strTok->String().Contains("stackdeep")) {
            fStackDeep  = strNum->String().Atoi();
         }
         if (strTok->String().Contains("maxlength")) {
            fMaxStringLength  = strNum->String().Atoi();
         }
      }
   }
   char currentOption[1000];
   sprintf(currentOption, "order %d sortstat %d sortstamp %d sortdeep %d stackdeep %d maxlength %d",
           fOrder, fSortStat, fSortStamp, fSortDeep, fStackDeep, fMaxStringLength);
   fOption = currentOption;
   if (str.Contains("?")) {
      printf("Options   : %s\n", fOption.Data());
      printf("order     : 0 - increasing 1 - decreasing\n");
      printf("sortstat  : 0 - TotalAllocCount 1 -  TotalAlocSize  2 - AllocCount 3 - AllocSize\n");
      printf("sortstamp : 0 - Current 1 -  MaxSize  2 - MaxCount\n");
      printf("sortdeep  : (0-inf) number of info to print\n");
      printf("stackdeep : (0-inf) deepnes of stack\n");
      printf("maxlength : (0-inf) maximal length of function (truncation after maxlength)");
   }
   delete tokens;
}
void TMemStat::RefreshSelect()
{
   
   if (fSelectedCodeIndex.empty())
      SelectCode(NULL, NULL, TMemStat::kOR);
   if (fSelectedStackIndex.empty())
      SelectStack(TMemStat::kOR);
}
Last change: Wed Jun 25 08:49:27 2008
Last generated: 2008-06-25 08:49
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.