#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(static_cast<Int_t>(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);
}