Skip to content
Snippets Groups Projects
Commit d44e1d7e authored by Rolf Seuster's avatar Rolf Seuster Committed by Graeme Stewart
Browse files

adjust to new LCG_80 - namely new Boost (AthenaAuditors-00-00-13)

	* Tagging AthenaAuditors-00-00-13.
	* adjust to new LCG_80 - namely new Boost

2015-11-12  Rolf Seuster

	* Tagging AthenaAuditors-00-00-12.
	* stdcmalloc for AthMemoryAuditor currently depreciated, added support for faster tcmalloc

2015-09-15  scott snyder  <snyder@bnl.gov>

	* Tagging AthenaAuditors-00-00-11.
	* Comply with ATLAS naming conventions.
parent 276d1129
No related merge requests found
......@@ -10,6 +10,7 @@ use GaudiInterface GaudiInterface-* External
use AtlasGdb AtlasGdb-* External
use AtlasBoost AtlasBoost-* External
use AtlasLibUnwind AtlasLibUnwind-* External
use AtlasGPerfTools AtlasGPerfTools-* External
private
use CoWTools CoWTools-* Control
......
......@@ -26,7 +26,11 @@
#include <dlfcn.h>
#include <sstream>
#include "memory_hooks.h"
#include "memory_hooks-common.h"
#include "memory_hooks-stdcmalloc.h"
#include "memory_hooks-tcmalloc.h"
bool AthMemoryAuditor::m_usetcmalloc=true;
AthMemoryAuditor::AthMemoryAuditor( const std::string& name,
ISvcLocator* pSvcLocator ) :
......@@ -43,11 +47,19 @@ AthMemoryAuditor::AthMemoryAuditor( const std::string& name,
}
AthMemoryAuditor::~AthMemoryAuditor()
{
{
ATH_MSG_INFO("In Destructor");
}
StatusCode
AthMemoryAuditor::finalize()
{
// silence when called outside of athena
if ( current_stage > 1 )
{
ATH_MSG_INFO("In Destructor");
if(m_usetcmalloc)
uninstall();
ATH_MSG_INFO("In finalize");
if(!m_reported)
{
report();
......@@ -56,16 +68,27 @@ AthMemoryAuditor::~AthMemoryAuditor()
ATH_MSG_INFO("");
ATH_MSG_INFO("Malloc Statistics:");
ATH_MSG_INFO("number of mallocs : " << counter_m);
ATH_MSG_INFO("number of frees : " << counter_f);
ATH_MSG_INFO(" no associated malloc : " << counter_fna);
ATH_MSG_INFO("number of reallocs : " << counter_r);
ATH_MSG_INFO(" to shrink : " << counter_rs);
ATH_MSG_INFO(" to grow : " << counter_rg);
ATH_MSG_INFO(" used as malloc : " << counter_rm);
ATH_MSG_INFO(" used as free : " << counter_rf);
ATH_MSG_INFO("number of memalign : " << counter_ma);
if(m_usetcmalloc)
{
ATH_MSG_INFO("number of mallocs : " << counter_tc_m);
ATH_MSG_INFO("number of frees : " << counter_tc_f);
ATH_MSG_INFO(" allocated then freed : " << counter_tc_mtf);
ATH_MSG_INFO("mmaped : " << counter_tc_mm);
ATH_MSG_INFO("munmaped : " << counter_tc_mum);
}
else
{
ATH_MSG_INFO("number of mallocs : " << counter_m);
ATH_MSG_INFO("number of frees : " << counter_f);
ATH_MSG_INFO(" no associated malloc : " << counter_fna);
ATH_MSG_INFO("number of reallocs : " << counter_r);
ATH_MSG_INFO(" to shrink : " << counter_rs);
ATH_MSG_INFO(" to grow : " << counter_rg);
ATH_MSG_INFO(" unknown : " << counter_rnr);
ATH_MSG_INFO(" used as malloc : " << counter_rm);
ATH_MSG_INFO(" used as free : " << counter_rf);
ATH_MSG_INFO("number of memalign : " << counter_ma);
}
// some memory statistics for debugging
if (this->msgLvl(MSG::DEBUG))
{
......@@ -76,7 +99,68 @@ AthMemoryAuditor::~AthMemoryAuditor()
ATH_MSG_DEBUG(line);
}
}
// we are done. When cleaning up itself, crash might occure, so let's not free
// anything anymore...
finished=true;
}
return StatusCode::SUCCESS;
}
StatusCode AthMemoryAuditor::initialize()
{
current_stage=2;
m_reported=false;
int l(0);
algorithms[l]="N/A";
arrayAlgIndex["N/A"]=aiStruct(l,m_defaultStacktraceDepth); ++l;
algorithms[l]="'framework'";
arrayAlgIndex["'framework'"]=aiStruct(l,m_defaultStacktraceDepth); ++l;
stacktraceDepth=m_defaultStacktraceDepth;
collectStacktraces=bool(m_defaultStacktraceDepth);
ATH_MSG_INFO("==> initialize");
for(auto it=m_depthPerAlg.begin(); it!=m_depthPerAlg.end(); ++it )
{
ATH_MSG_INFO("INIT " << *it);
std::istringstream buffer(*it);
std::string s;
int r=0;
buffer >> s >> r;
ATH_MSG_INFO("INIT leaks in algorithm " << s << " will have stacktrace depth of " << r );
arrayAlgIndex[s]=aiStruct(l,r);
algorithms[l]=s;
++l;
}
curMaxIndex=l-1;
// replace test with coe from here
// perftest/Control/AthenaAuditors/src/TCMallocAuditor.cxx: MallocExtension::instance()->GetNumericProperty("generic.current_allocated_bytes", &m_value);
// TCTEST/Control/AthenaAuditors/src/FPEAuditor.cxx:bool MallocExtension::GetNumericProperty(const char* /* property */, size_t* /* value*/ ) { return true; }
// TCTEST/Control/AthenaAuditors/src/FPEAuditor.cxx: MallocExtension::instance()->GetNumericProperty("generic.current_allocated_bytes", &value);
if ( ! initialized )
{
// If tcmalloc is not preloaded this call goes to our implementation which will set m_usetcmalloc to false
MallocExtension::instance();
if(m_usetcmalloc)
{
ATH_MSG_INFO("Using hooks for tcmalloc");
my_init_tcmalloc();
}
else
{
ATH_MSG_INFO("Using hooks for stdcmalloc");
ATH_MSG_WARNING("stdcmalloc is currently not well supported, consider using the much faster tcmalloc implementation");
my_init_hook();
}
}
return StatusCode::SUCCESS;
}
void AthMemoryAuditor::report()
......@@ -109,66 +193,41 @@ void AthMemoryAuditor::report()
std::vector<unsigned long> leaksInStage(10,0);
std::vector<unsigned long> leakedMemInStage(10,0);
myBlocks *b=new myBlocks();
myBlocks *b2=new myBlocks();
myBlocks_tc *b=new myBlocks_tc();
myBlocks_tc *b2=new myBlocks_tc();
struct info
{
uint32_t total_size;
std::vector<node*> l;
std::vector<allocSet_tc::iterator> l;
std::vector<uintptr_t> hash;
};
std::map<uint32_t,std::map<uint32_t,info> > accum;
for ( unsigned int reportStage(0); reportStage<8; ++reportStage )
// first the code for tcmalloc
if(m_usetcmalloc)
{
node* nf(m_first.getNext());
node* np(m_first.getNext());
node* nn(m_first.getNext());
while ( nf != &m_last )
for( allocSet_tc::iterator it=allocset_tc.begin(); it!=allocset_tc.end(); ++it )
{
nn=nf->getNext();
size_t size = nf->getSize();
redzone *r = new ((void*)((uintptr_t)(nf)+deltaLow+size)) redzone( false );
uint32_t stage = r->getStage();
uint32_t context = r->getAlgIndex();
np=nf;
nf=nn;
if( reportStage==0 )
if( stage < 1E6 || stage >= 9E7 )
continue;
if(reportStage==1)
if(stage != 1 )
continue;
if(reportStage==2)
if(stage != 2 )
continue;
if(reportStage==3)
if(stage != 3 )
continue;
if(reportStage==4)
if(stage != 4 )
continue;
if(reportStage==5)
if(stage != 1E6-10 )
continue;
if(reportStage==6)
if(stage != 9E7 )
continue;
if(reportStage==7)
if(stage != 1E8-2 )
continue;
unsigned int reportStage(0);
uint32_t stage = it->curstage;
size_t size = it->allocsize;
uint32_t context = it->algindex;
reportStage=stage;
if( stage >= 1E6 && stage < 9E7 )
reportStage=0;
if(stage == 1E6-10 )
reportStage=5;
if(stage == 9E7 )
reportStage=6;
if(stage == 1E8-2 )
reportStage=7;
leaksInStage[reportStage]++;
leakedMemInStage[reportStage]+=size;
uintptr_t h(0);
b->allocated=(uintptr_t)(np);
allocSet::iterator it = allocset.find(*b);
if (it!=allocset.end())
if (it!=allocset_tc.end())
{
if(it->allocatedFrom.size()>=2)
h=(uintptr_t)it->allocatedFrom[1];
......@@ -178,10 +237,94 @@ void AthMemoryAuditor::report()
}
accum[stage][context].total_size+=size;
accum[stage][context].l.push_back(np);
accum[stage][context].l.push_back(it);
accum[stage][context].hash.push_back(h);
}
}
else
{
for ( unsigned int reportStage(0); reportStage<8; ++reportStage )
{
for ( std::map<uint32_t,info>::const_iterator it=accum[reportStage].begin(); it!=accum[reportStage].end(); ++it )
std::cerr << " NOW " << it->first << " / " << it->second.total_size << "\n";
// accum[stage][context].total_size+=size;
}
for ( unsigned int reportStage(0); reportStage<8; ++reportStage )
{
/* std::cerr << "INIT : s_first / s_last " << &s_first << " / " << &s_last << "\n";
std::cerr << "INIT : s_first / s_last "
<< s_first.getNext() << " / " << s_last.getPrev() << "\n"; */
node* nf(s_first.getNext());
node* np(s_first.getNext());
node* nn(s_first.getNext());
while ( nf != &s_last )
{
// std::cerr << "INIT : nf " << nf << "\n";
nn=nf->getNext();
size_t size = nf->getSize();
redzone *r = new ((void*)((uintptr_t)(nf)+deltaLow+size)) redzone( false );
uint32_t stage = r->getStage();
uint32_t context = r->getAlgIndex();
np=nf;
nf=nn;
if( reportStage==0 )
if( stage < 1E6 || stage >= 9E7 )
continue;
if(reportStage==1)
if(stage != 1 )
continue;
if(reportStage==2)
if(stage != 2 )
continue;
if(reportStage==3)
if(stage != 3 )
continue;
if(reportStage==4)
if(stage != 4 )
continue;
if(reportStage==5)
if(stage != 1E6-10 )
continue;
if(reportStage==6)
if(stage != 9E7 )
continue;
if(reportStage==7)
if(stage != 1E8-2 )
continue;
leaksInStage[reportStage]++;
leakedMemInStage[reportStage]+=size;
uintptr_t h(0);
b->allocated=(uintptr_t)(np+np->getDeltaPayload());
allocSet_tc::iterator it = allocset_tc.find(*b);
if (it!=allocset_tc.end())
{
if(it->allocatedFrom.size()>=2)
h=(uintptr_t)it->allocatedFrom[1];
for ( unsigned int j = 2; j < it->allocatedFrom.size(); j++)
if(it->allocatedFrom[j])
h^=(uintptr_t)it->allocatedFrom[j];
/* std::cerr << "RS find : "
<< size << " " << it->allocsize << " | "
<< stage << " " << it->curstage << "\n"; */
it->allocsize = size;
it->curstage = stage;
// it->context = algindex;
}
accum[stage][context].total_size+=size;
accum[stage][context].l.push_back(it);
accum[stage][context].hash.push_back(h);
}
}
}
std::cerr << "Summary\n" ;
std::cerr << " " << leaksInStage[0] << " Reported leak(s) allocated in event loop, leaking " << leakedMemInStage[0] << " bytes\n";
......@@ -273,7 +416,7 @@ void AthMemoryAuditor::report()
else
{
stacktraceDepth=fit->second.stacktrace;
// std::cerr << " ROLF : stacktracesize " << stacktraceDepth << "\n";
if(stacktraceDepth > 0 )
{
std::vector<info> thisAlg;
......@@ -284,20 +427,22 @@ void AthMemoryAuditor::report()
{
info leakSum;
size_t size = imax->second.l[i_tr]->getSize();
redzone *r = new ((void*)((uintptr_t)imax->second.l[i_tr]+deltaLow+size)) redzone( false );
uint32_t stage = r->getStage();
size_t size = imax->second.l[i_tr]->allocsize;
// redzone *r = new ((void*)((uintptr_t)imax->second.l[i_tr]+deltaLow+size)) redzone( false );
uint32_t stage = imax->second.l[i_tr]->curstage;
leakSum.total_size=size;
leakSum.l.push_back(imax->second.l[i_tr]);
leakSum.hash.push_back(stage);
// std::cerr << " ROLF : stage " << stage << " " << size << "\n";
// stage == 0 means, this leak was reported earlier with another leak with same stacktrace
if(stage>0)
{
b->allocated=(uintptr_t)imax->second.l[i_tr];
allocSet::iterator it = allocset.find(*b);
if (it!=allocset.end())
b->allocated=(uintptr_t)imax->second.l[i_tr]->allocated;
allocSet_tc::iterator it = allocset_tc.find(*b);
if (it!=allocset_tc.end())
{
bool same=true;
unsigned int i_tr2 = i_tr+1;
......@@ -305,15 +450,15 @@ void AthMemoryAuditor::report()
{
if ( imax->second.hash[i_tr] == imax->second.hash[i_tr2] )
{
size = imax->second.l[i_tr2]->getSize();
redzone *r2 = new ((void*)((uintptr_t)imax->second.l[i_tr2]+deltaLow+size)) redzone( false );
stage = r2->getStage();
size = imax->second.l[i_tr2]->allocsize;
// redzone *r2 = new ((void*)((uintptr_t)imax->second.l[i_tr2]+deltaLow+size)) redzone( false );
stage = imax->second.l[i_tr2]->curstage;
if(stage>0)
{
b2->allocated=(uintptr_t)imax->second.l[i_tr2];
allocSet::iterator it2 = allocset.find(*b2);
if (it2!=allocset.end())
b2->allocated=(uintptr_t)imax->second.l[i_tr2]->allocated;
allocSet_tc::iterator it2 = allocset_tc.find(*b2);
if (it2!=allocset_tc.end())
{
same=true;
for ( unsigned int j = 0; j < std::min(it->allocatedFrom.size(),it2->allocatedFrom.size()); j++)
......@@ -322,8 +467,8 @@ void AthMemoryAuditor::report()
same=false;
if(same)
{
redzone *r2 = new ((void*)((uintptr_t)imax->second.l[i_tr2]+deltaLow+size)) redzone( false );
stage = r2->getStage();
// redzone *r2 = new ((void*)((uintptr_t)imax->second.l[i_tr2]+deltaLow+size)) redzone( false );
stage = imax->second.l[i_tr2]->curstage;
leakSum.total_size+=size;
// how many leaks with same stacktrace ?
......@@ -331,7 +476,7 @@ void AthMemoryAuditor::report()
leakSum.hash.push_back(stage);
// set stage to zero to suppress further printout
r2->clearStage();
imax->second.l[i_tr2]->curstage=0;
}
}
}
......@@ -348,24 +493,30 @@ void AthMemoryAuditor::report()
int nleaks(0);
int mleaks(0);
uint32_t stage(0);
while(thisAlg.size())
{
auto itmax = thisAlg.begin();
for(auto iter=thisAlg.begin(); iter!=thisAlg.end(); ++iter)
if(itmax->total_size < iter->total_size)
itmax=iter;
stage = itmax->hash[0];
std::multimap<int,int> here;
auto itmax = thisAlg.end();
itmax--;
// if(thisAlg.size()%100000==0)
// std::cerr << " RS " << thisAlg.size() << "\n";
if(stmax>=0)
{
itmax = thisAlg.begin();
for(auto iter=thisAlg.begin(); iter!=thisAlg.end(); ++iter)
if(itmax->total_size < iter->total_size)
itmax=iter;
stage = itmax->hash[0];
std::multimap<int,int> here;
std::cerr << " " << itmax->l.size() << " leak(s) in algorithm " << str << " allocated in "
<< stageToString(stage) << " with total size of " << itmax->total_size << " bytes";
if(itmax->l.size()>1)
{
for(auto i = itmax->l.begin(); i != itmax->l.end(); ++i )
here.insert(std::pair<int, int>((*i)->getSize(), 1));
here.insert(std::pair<int, int>((*i)->allocsize, 1));
std::string s("");
auto it = here.end(); --it;
......@@ -386,31 +537,32 @@ void AthMemoryAuditor::report()
std::cerr << "\n";
// print stacktrace
b->allocated=(uintptr_t)itmax->l[0];
allocSet::iterator it = allocset.find(*b);
// b->allocated=(uintptr_t)itmax->l[0]->allocated;
// allocSet::iterator it = allocset.find(*b);
allocSet_tc::iterator it = itmax->l[0];
if (it!=allocset.end())
for ( unsigned int j = 1; j < it->allocatedFrom.size() ; j++)
{
if(it->allocatedFrom[j])
{
fprintf(stderr,"%7d ",j);
Dl_info info;
ptrdiff_t relative_address(0);
const char *libname = "N/A";
if (dladdr (it->allocatedFrom[j], &info) && info.dli_fname && info.dli_fname[0])
{
libname = info.dli_fname;
// difference of two pointers
uintptr_t p1=(uintptr_t)it->allocatedFrom[j];
uintptr_t p2=(uintptr_t)info.dli_fbase;
relative_address = (p1 > p2) ? p1 - p2 : p2 - p1;
if (strstr (info.dli_fname, ".so") == 0)
relative_address = p1;
}
fprintf(stderr," %s D[%p]\n",libname,(void*)relative_address);
}
}
// if (it!=allocset.end())
for ( unsigned int j = 1; j < it->allocatedFrom.size() ; j++)
{
if(it->allocatedFrom[j])
{
fprintf(stderr,"%7d ",j);
Dl_info info;
ptrdiff_t relative_address(0);
const char *libname = "N/A";
if (dladdr (it->allocatedFrom[j], &info) && info.dli_fname && info.dli_fname[0])
{
libname = info.dli_fname;
// difference of two pointers
uintptr_t p1=(uintptr_t)it->allocatedFrom[j];
uintptr_t p2=(uintptr_t)info.dli_fbase;
relative_address = (p1 > p2) ? p1 - p2 : p2 - p1;
if (strstr (info.dli_fname, ".so") == 0)
relative_address = p1;
}
fprintf(stderr," %s D[%p]\n",libname,(void*)relative_address);
}
}
}
else
{
......@@ -432,8 +584,9 @@ void AthMemoryAuditor::report()
leaks.erase(imax);
}
}
delete b;
delete b2;
// delete b;
// delete b2;
}
}
......@@ -462,50 +615,6 @@ std::string AthMemoryAuditor::stageToString(long s)
return str;
}
StatusCode AthMemoryAuditor::initialize()
{
current_stage=2;
m_reported=false;
int l(0);
algorithms[l]="N/A";
arrayAlgIndex["N/A"]=aiStruct(l,m_defaultStacktraceDepth); ++l;
algorithms[l]="'framework'";
arrayAlgIndex["'framework'"]=aiStruct(l,m_defaultStacktraceDepth); ++l;
stacktraceDepth=m_defaultStacktraceDepth;
collectStacktraces=bool(m_defaultStacktraceDepth);
ATH_MSG_INFO("==> initialize");
for(auto it=m_depthPerAlg.begin(); it!=m_depthPerAlg.end(); ++it )
{
ATH_MSG_INFO("INIT " << *it);
std::istringstream buffer(*it);
std::string s;
int r=0;
buffer >> s >> r;
ATH_MSG_INFO("INIT leaks in algorithm " << s << " will have stacktrace depth of " << r );
arrayAlgIndex[s]=aiStruct(l,r);
algorithms[l]=s;
++l;
}
curMaxIndex=l-1;
if ( getenv("USETCMALLOCMINIMAL") )
{
if ( ! initialized )
my_init_hook();
}
else
{
ATH_MSG_WARNING("Please run with standard malloc to enable the auditor: athena.py <jobOptions> --stdcmalloc");
}
return StatusCode::SUCCESS;
}
void AthMemoryAuditor::beforeInitialize(INamedInterface* comp)
{
// ATH_MSG_INFO("==> beforeInitialize " << comp->name() << " . " << initialized );
......
......@@ -43,6 +43,8 @@ public:
virtual ~AthMemoryAuditor();
virtual StatusCode initialize();
virtual StatusCode finalize();
virtual void beforeInitialize(INamedInterface* alg);
virtual void beforeReinitialize(INamedInterface* alg);
......@@ -61,6 +63,8 @@ public:
bool m_reported;
static bool m_usetcmalloc;
private:
int m_stmax;
......
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
// common code for memory_hooks for tcmalloc and stdcmalloc which are used for the AthMemoryAuditor
// Rolf Seuster, Oct 2015
#ifndef ATHENAAUDITORS_MEMORYHOOKSCOMMON_H
#define ATHENAAUDITORS_MEMORYHOOKSCOMMON_H
#include <iostream>
#include <fstream>
#include <iomanip>
// needed for implementing hooks into tcmalloc
#include "gperftools/malloc_hook.h"
#include <cstdint>
#include <string.h>
#include <stdlib.h> // for getenv
#include <boost/intrusive/splay_set.hpp>
#define UNW_LOCAL_ONLY
#include "libunwind.h"
struct aiStruct
{
aiStruct() : index(0), stacktrace(0) {};
aiStruct(uint16_t i, uint16_t s) : index(i), stacktrace(s) {};
uint16_t index;
uint16_t stacktrace;
};
static std::map<std::string, aiStruct> arrayAlgIndex;
static std::map<uint32_t, std::string> algorithms;
static uint32_t curMaxIndex(0);
static uint32_t curIndex(0);
static bool initialized(false);
static bool finished(false);
static uintptr_t context(0);
static uintptr_t contextFirst(0);
static uint32_t current_stage(0);
static std::string defaultString = "N/A";
static size_t stacktraceDepth(25);
static bool collectStacktraces(true);
using namespace boost::intrusive;
class myBlocks_tc : public bs_set_base_hook<optimize_size<false> >
{
public:
uintptr_t allocated;
uintptr_t allocsize;
uint32_t algindex;
uint32_t curstage;
std::vector<void*> allocatedFrom;
public:
bs_set_member_hook<> member_hook_;
myBlocks_tc()
: allocated(0)
, allocsize(0)
, algindex(0)
, curstage(0)
{ };
myBlocks_tc(uintptr_t mem, uintptr_t s, uint32_t algi, uint32_t cstage, size_t stDepth)
: allocated(mem)
, allocsize(s)
, algindex(algi)
, curstage(cstage)
, allocatedFrom(stDepth,nullptr) { };
friend bool operator< ( const myBlocks_tc &a, const myBlocks_tc &b )
{
return a.allocated < b.allocated;
};
friend bool operator> ( const myBlocks_tc &a, const myBlocks_tc &b )
{
return a.allocated > b.allocated;
};
friend bool operator== ( const myBlocks_tc &a, const myBlocks_tc &b)
{
return a.allocated == b.allocated;
};
};
myBlocks_tc *bg_tc;
typedef splay_set< myBlocks_tc, base_hook<bs_set_base_hook<> > > allocSet_tc;
static allocSet_tc::iterator allocset_last;
static allocSet_tc allocset_tc;
static allocSet_tc free_set_tc;
#endif
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
// memory_hooks for tcmalloc which are used for the AthMemoryAuditor
// Rolf Seuster, Oct 2015
#ifndef ATHENAAUDITORS_MEMORYHOOKSTCMALLOC_H
#define ATHENAAUDITORS_MEMORYHOOKSTCMALLOC_H
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdint>
#include <string.h>
#include <stdlib.h> // for getenv
// hooks and utilities from tcmalloc
#include <gperftools/malloc_extension.h>
#include <gperftools/malloc_hook.h>
#include <gperftools/stacktrace.h>
#include "gperftools/tcmalloc.h"
// various counters needed
static long long counter_tc_m(0);
static long long counter_tc_f(0);
static long long counter_tc_mtf(0);
static long long counter_tc_mm(0);
static long long counter_tc_mum(0);
/////////////////////////////////////////////////////////////////////
//////// tcmalloc start
/////////////////////////////////////////////////////////////////////
// define empty stubs, these will be interposed by the real tcmalloc
// if they are actually called the job is badly misconfigured - should never happen
int MallocHook_RemoveNewHook(MallocHook_NewHook)
{ std::cerr << "TCMALLOC HOOKS: RemoveNewHook - Should not be here\n"; abort(); return 1; }
int MallocHook_RemoveDeleteHook(MallocHook_DeleteHook)
{ std::cerr << "TCMALLOC HOOKS: RemoveDeleteHook - Should not be here\n"; abort(); return 1; }
int MallocHook_AddNewHook(MallocHook_NewHook)
{ std::cerr << "TCMALLOC HOOKS: AddNewHook - Should not be here\n"; abort(); return 1; }
int MallocHook_AddDeleteHook(MallocHook_DeleteHook)
{ std::cerr << "TCMALLOC HOOKS: AddDeleteHook - Should not be here\n"; abort(); return 1; }
// both are not really implemented yet, just counting - FIXME to be done
int MallocHook_AddMmapHook(MallocHook_MmapHook)
{ std::cerr << "TCMALLOC HOOKS: AddMmapHook - Should not be here\n"; abort(); return 1; }
int MallocHook_AddMunmapHook(MallocHook_MunmapHook)
{ std::cerr << "TCMALLOC HOOKS: AddMunmapHook - Should not be here\n"; abort(); return 1; }
// interpose this as well - we use this to discover if we have tcmalloc preloaded
MallocExtension* MallocExtension::instance() { AthMemoryAuditor::m_usetcmalloc=false; return nullptr; }
void athena_NewHook(const void* ptr, size_t size)
{
counter_tc_m++;
MallocHook_RemoveNewHook(&athena_NewHook);
myBlocks_tc *b = new myBlocks_tc( (uintptr_t)ptr, size, curIndex, current_stage, stacktraceDepth );
if(collectStacktraces)
{
b->allocatedFrom.resize(stacktraceDepth);
unw_backtrace (b->allocatedFrom.data(), b->allocatedFrom.capacity());
}
std::pair<allocSet_tc::iterator, bool> i = allocset_tc.insert( *b );
if(!i.second)
{
std::cerr << "ALREADY EXISTING " << std::hex << ptr << std::dec << "\n";
}
allocset_last=i.first;
MallocHook_AddNewHook(&athena_NewHook);
}
void athena_DeleteHook(const void* ptr)
{
counter_tc_f++;
if(ptr==nullptr)
{
counter_tc_mtf++;
return;
}
MallocHook_RemoveDeleteHook(&athena_DeleteHook);
if ( allocset_last == allocset_tc.end() || allocset_last->allocated != (uintptr_t)ptr )
{
bg_tc->allocated=(uintptr_t)ptr;
allocSet_tc::iterator i = allocset_tc.find( *bg_tc );
if ( i != allocset_tc.end() )
{
allocset_tc.erase(i);
delete &(*i);
}
}
else
{
counter_fna++;
// std::cerr << "TCMALLOC delete-last\n";
allocset_tc.erase(allocset_last);
delete &(*allocset_last);
allocset_last = allocset_tc.end();
}
MallocHook_AddDeleteHook(&athena_DeleteHook);
}
/* not fully implemented yet, just counting */
void athena_MmapHook(const void* /* result */,
const void* /* start */,
size_t /* size */,
int /* protection */,
int /* flags */,
int /* fd */,
off_t /* offset */)
{
counter_tc_mm++;
// std::cerr << "TCMALLOC mmap" << std::hex << result << " " << size << std::dec << "\n";
}
void athena_MunmapHook(const void* /* ptr */, size_t /* size */)
{
counter_tc_mum++;
// std::cerr << "TCMALLOC munmap " << std::hex << ptr << " " << size << std::dec << "\n";
}
void uninstall()
{
MallocHook_RemoveNewHook(&athena_NewHook);
MallocHook_RemoveDeleteHook(&athena_DeleteHook);
}
void my_init_tcmalloc()
{
bg_tc = new myBlocks_tc();
allocset_last=allocset_tc.end();
if(MallocHook::AddNewHook(&athena_NewHook))
std::cerr << "TCMALLOC NEW HOOK OK\n";
if(MallocHook::AddDeleteHook(&athena_DeleteHook))
std::cerr << "TCMALLOC DELETE HOOK OK\n";
if(MallocHook::AddMmapHook(&athena_MmapHook))
std::cerr << "TCMALLOC MMAP HOOK OK\n";
if(MallocHook::AddMunmapHook(&athena_MunmapHook))
std::cerr << "TCMALLOC MUNMAP HOOK OK\n";
initialized=true;
}
#endif
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