Skip to content
Snippets Groups Projects
Commit d78128ca authored by Anar Manafov's avatar Anar Manafov
Browse files

The first step of optimizations:

   - remove string digests (cost too much)
   - use a simple pre-caching of digests and ids
   - cosmetic changes


git-svn-id: http://root.cern.ch/svn/root/trunk@35571 27541ba8-7e3a-0410-8455-c3a389f83636
parent 85005688
No related branches found
No related tags found
No related merge requests found
...@@ -25,7 +25,7 @@ namespace memstat { ...@@ -25,7 +25,7 @@ namespace memstat {
// //
size_t getBacktrace(void **_trace, size_t _size, Bool_t _bUseGNUBuiltinBacktrace = kFALSE); size_t getBacktrace(void **_trace, size_t _size, Bool_t _bUseGNUBuiltinBacktrace = kFALSE);
int getSymbols(void *_pAddr, int getSymbols(void *_pAddr,
TString &_strInfo, TString &_strLib, TString &_strSymbol, TString &_strLine); TString &_strInfo, TString &_strLib, TString &_strSymbol);
void getSymbolFullInfo(void *_pAddr, TString *_retInfo, const char *const _seporator = " | "); void getSymbolFullInfo(void *_pAddr, TString *_retInfo, const char *const _seporator = " | ");
void demangle(char *_codeInfo, TString &_str); void demangle(char *_codeInfo, TString &_str);
} }
......
...@@ -50,8 +50,29 @@ namespace memstat { ...@@ -50,8 +50,29 @@ namespace memstat {
Container_t fContainer; Container_t fContainer;
}; };
const UShort_t g_digestSize = 16;
struct SCustomDigest {
SCustomDigest() {
memset(fValue, 0, g_digestSize);
}
SCustomDigest(UChar_t _val[g_digestSize]) {
memcpy(fValue, _val, g_digestSize);
}
UChar_t fValue[g_digestSize];
};
inline bool operator< (const SCustomDigest &a, const SCustomDigest &b)
{
for(int i = 0; i < g_digestSize; ++i) {
if(a.fValue[i] != b.fValue[i])
return (a.fValue[i] < b.fValue[i]);
}
return false;
}
class TMemStatMng: public TObject { class TMemStatMng: public TObject {
typedef std::map<std::string, Int_t> CRCSet_t; typedef std::map<SCustomDigest, Int_t> CRCSet_t;
private: private:
TMemStatMng(); TMemStatMng();
...@@ -80,6 +101,8 @@ namespace memstat { ...@@ -80,6 +101,8 @@ namespace memstat {
static void FreeHook(void* ptr, const void* /*caller*/); static void FreeHook(void* ptr, const void* /*caller*/);
static void MacAllocHook(void *ptr, size_t size); static void MacAllocHook(void *ptr, size_t size);
static void MacFreeHook(void *ptr); static void MacFreeHook(void *ptr);
Int_t generateBTID(UChar_t *CRCdigest, Int_t stackEntries,
void **stackPointers);
// memory information // memory information
......
...@@ -144,7 +144,7 @@ namespace memstat { ...@@ -144,7 +144,7 @@ namespace memstat {
//______________________________________________________________________________ //______________________________________________________________________________
int getSymbols(void *_pAddr, int getSymbols(void *_pAddr,
TString &/*_strInfo*/, TString &_strLib, TString &_strSymbol, TString &/*_strLine*/) TString &/*_strInfo*/, TString &_strLib, TString &_strSymbol)
{ {
// get the name of the function and library // get the name of the function and library
...@@ -186,15 +186,15 @@ namespace memstat { ...@@ -186,15 +186,15 @@ namespace memstat {
TString strInfo; TString strInfo;
TString strLib; TString strLib;
TString strFun; TString strFun;
TString strLine; int res = getSymbols(_pAddr, strInfo, strLib, strFun);
int res = getSymbols(_pAddr, strInfo, strLib, strFun, strLine);
if(0 != res) if(0 != res)
return; return;
*_retInfo += *_retInfo += strInfo;
strInfo + _separator + *_retInfo += _separator;
strLib + _separator + *_retInfo += strLib;
strFun; *_retInfo += _separator;
*_retInfo += strFun;
#else #else
if(_pAddr || _separator) { } if(_pAddr || _separator) { }
#endif #endif
......
...@@ -263,59 +263,68 @@ void TMemStatMng::FreeHook(void* ptr, const void* /*caller*/) ...@@ -263,59 +263,68 @@ void TMemStatMng::FreeHook(void* ptr, const void* /*caller*/)
} }
//______________________________________________________________________________ //______________________________________________________________________________
void TMemStatMng::AddPointer(void *ptr, Int_t size) Int_t TMemStatMng::generateBTID(UChar_t *CRCdigest, Int_t stackEntries,
void **stackPointers)
{ {
// Add pointer to table. // An internal function, which returns a bitid for a corresponding CRC digest
// This method is called every time when any of the hooks are triggered.
// The memory de-/allocation information will is recorded. // cache variables
static Int_t old_btid = -1;
void *stptr[g_BTStackLevel + 1]; static SCustomDigest old_digest;
const int stackentries = getBacktrace(stptr, g_BTStackLevel, fUseGNUBuiltinBacktrace);
Int_t ret_val = -1;
bool startCheck(false);
if(old_btid >= 0) {
for(int i = 0; i < g_digestSize; ++i) {
if(old_digest.fValue[i] != CRCdigest[i]) {
startCheck = true;
break;
}
}
ret_val = old_btid;
} else {
startCheck = true;
}
// save only unique BTs // return cached value
TMD5 md5; if(!startCheck)
md5.Update(reinterpret_cast<UChar_t*>(stptr), sizeof(void*) * stackentries); return ret_val;
md5.Final();
string crc_digest(md5.AsString());
// for Debug. A counter of all (de)allacations. old_digest = SCustomDigest(CRCdigest);
++fBTIDCount; CRCSet_t::const_iterator found = fBTChecksums.find(CRCdigest);
CRCSet_t::const_iterator found = fBTChecksums.find(crc_digest);
// TODO: define a proper default value
Int_t btid = -1;
if(fBTChecksums.end() == found) { if(fBTChecksums.end() == found) {
// check the size of the BT array container // check the size of the BT array container
const int nbins = fHbtids->GetNbinsX(); const int nbins = fHbtids->GetNbinsX();
//check that the current allocation in fHbtids is enough, otherwise expend it with //check that the current allocation in fHbtids is enough, otherwise expend it with
if(fBTCount + stackentries + 1 >= nbins) { if(fBTCount + stackEntries + 1 >= nbins) {
fHbtids->SetBins(nbins * 2, 0, 1); fHbtids->SetBins(nbins * 2, 0, 1);
} }
int *btids = fHbtids->GetArray(); int *btids = fHbtids->GetArray();
// A first value is a number of entries in a given stack // A first value is a number of entries in a given stack
btids[fBTCount++] = stackentries; btids[fBTCount++] = stackEntries;
btid = fBTCount; ret_val = fBTCount;
if(stackentries <= 0) { if(stackEntries <= 0) {
Warning("AddPointer", Warning("AddPointer",
"A number of stack entries is equal or less than zero. For btid %d", btid); "A number of stack entries is equal or less than zero. For btid %d", ret_val);
} }
// add new BT's CRC value // add new BT's CRC value
pair<CRCSet_t::iterator, bool> res = fBTChecksums.insert(CRCSet_t::value_type(crc_digest, btid)); pair<CRCSet_t::iterator, bool> res = fBTChecksums.insert(CRCSet_t::value_type(CRCdigest, ret_val));
if(!res.second) if(!res.second)
Error("AddPointer", "Can't added a new BTID to the container."); Error("AddPointer", "Can't added a new BTID to the container.");
// save all symbols of this BT // save all symbols of this BT
for(int i = 0; i < stackentries; ++i) { for(int i = 0; i < stackEntries; ++i) {
ULong_t func_addr = (ULong_t)(stptr[i]); ULong_t func_addr = (ULong_t)(stackPointers[i]);
Int_t idx = fFAddrs.find(func_addr); Int_t idx = fFAddrs.find(func_addr);
// check, whether it's a new symbol // check, whether it's a new symbol
if(idx < 0) { if(idx < 0) {
TString strFuncAddr; TString strFuncAddr;
strFuncAddr += func_addr; strFuncAddr += func_addr;
TString strSymbolInfo; TString strSymbolInfo;
getSymbolFullInfo(stptr[i], &strSymbolInfo); getSymbolFullInfo(stackPointers[i], &strSymbolInfo);
TNamed *nm = new TNamed(strFuncAddr, strSymbolInfo); TNamed *nm = new TNamed(strFuncAddr, strSymbolInfo);
fFAddrsList->Add(nm); fFAddrsList->Add(nm);
...@@ -331,9 +340,35 @@ void TMemStatMng::AddPointer(void *ptr, Int_t size) ...@@ -331,9 +340,35 @@ void TMemStatMng::AddPointer(void *ptr, Int_t size)
} else { } else {
// reuse an existing BT // reuse an existing BT
btid = found->second; ret_val = found->second;
} }
old_btid = ret_val;
return ret_val;
}
//______________________________________________________________________________
void TMemStatMng::AddPointer(void *ptr, Int_t size)
{
// Add pointer to table.
// This method is called every time when any of the hooks are triggered.
// The memory de-/allocation information will is recorded.
void *stptr[g_BTStackLevel + 1];
const int stackentries = getBacktrace(stptr, g_BTStackLevel, fUseGNUBuiltinBacktrace);
// save only unique BTs
TMD5 md5;
md5.Update(reinterpret_cast<UChar_t*>(stptr), sizeof(void*) * stackentries);
UChar_t digest[g_digestSize];
md5.Final(digest);
// for Debug. A counter of all (de)allacations.
++fBTIDCount;
Int_t btid(generateBTID(digest, stackentries, stptr));
if(btid <= 0) if(btid <= 0)
Error("AddPointer", "bad BT id"); Error("AddPointer", "bad BT id");
...@@ -347,4 +382,3 @@ void TMemStatMng::AddPointer(void *ptr, Int_t size) ...@@ -347,4 +382,3 @@ void TMemStatMng::AddPointer(void *ptr, Int_t size)
fBtID = btid; fBtID = btid;
fDumpTree->Fill(); fDumpTree->Fill();
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment