21 #include <unordered_map>
22 #include "boost/io/ios_state.hpp"
27 std::cout <<
"usage: " <<
prog <<
'\n'
28 <<
" -i <input_name> : file pattern to use for input"
37 typedef std::unordered_map< Address_t, std::string >
Symbols_t;
70 static std::string gUnknown =
"<unknown>";
101 for ( CallTree_t::const_iterator icp2 = cp2.
m_callees.begin();
108 cp1.
m_callees[ icp2->first ] = icp2->second;
135 unsigned long long size = 0;
141 icp != callpoint.
m_callees.end(); ++icp ) {
151 icp != callpoint.
m_callees.end(); ++icp ) {
165 const std::string& call_name =
getSymbol( call_info.second );
167 f <<
"fl=athena.cxx\n";
168 f <<
"fn=" << call_name <<
'\n';
170 <<
' ' << callpoint.
m_news <<
'\n';
177 for ( CallTree_t::const_iterator icp = callpoint.
m_callees.begin();
178 icp != callpoint.
m_callees.end(); ++icp ) {
179 f <<
"cfn=" <<
getSymbol( icp->first.second ) <<
'\n';
180 f <<
"calls=" << icp->second.m_called <<
' ' << icp->first.second <<
'\n';
181 f << icp->first.first <<
' ' << icp->second.m_inclusive
182 <<
' ' << icp->second.m_called <<
'\n';
186 for ( CallTree_t::const_iterator icp = callpoint.
m_callees.begin();
187 icp != callpoint.
m_callees.end(); ++icp ) {
195 std::cout <<
"reading symbols from " <<
input <<
" ... " << std::endl;
196 FILE* fsyms = popen( (
"gzip -dc " +
input).c_str(),
"r" );
199 while ( fread( (
void*)&
l,
sizeof(
l), 1, fsyms ) == 1) {
204 int stat = fread( &
c,
sizeof(
char), 1, fsyms );
205 if (
stat <= 0 ||
c ==
'\n')
break;
206 if (off <
sizeof(
s)-1)
213 if ( strcmp(
s,
"operator new(unsigned int)" ) == 0 )
215 else if ( strcmp(
s,
"operator new(unsigned int, std::nothrow_t const&)" ) == 0 )
218 else if ( strcmp(
s,
"operator new[](unsigned int)" ) == 0 )
221 else if ( strncmp(
s,
"std::", 5 ) == 0 ||
222 strncmp(
s,
"__gnu_cxx", 9 ) == 0 ||
223 strstr(
s,
"_S_construct" ) != 0 ||
224 strstr(
s,
"_M_allocate_and_copy" ) != 0 ) {
239 boost::io::ios_base_all_saver coutsave (std::cout);
241 if (
stat(
input.c_str(), &statbuf ) != 0 ) {
242 std::cout <<
"failed to stat " <<
input <<
" ... exiting ... " << std::endl;
246 double inv_total_bytes = 1. /
static_cast<double> (statbuf.st_size);
248 unsigned long long byte_counter = 0, stack_counter = 0, total_size = 0;
251 std::cout <<
"reading traces from " <<
input <<
" ... " << std::endl;
252 FILE* fprof = popen( (
"gzip -dc " +
input).c_str(),
"r" );
254 long size = 0, nstack = 0, step_progress = 0, progress = 0;
255 const int maxstack = 128;
258 std::cout.setf( std::ios::fixed, std::ios::floatfield );
259 std::cout << std::setprecision( 2 );
261 std::cout <<
" progress: ["; std::cout.flush();
262 while ( fread( (
void*)&
size,
sizeof(
long), 1, fprof ) ) {
263 if (fread( (
void*)&nstack,
sizeof(
long), 1, fprof ) < 1)
break;
267 else if (nstack > maxstack) {
268 nskip = nstack - maxstack;
271 if ((
long)fread( (
void*)stacktrace,
sizeof(
Address_t), nstack, fprof ) < nstack)
break;
274 if ((
long)fread( &dum,
sizeof(
Address_t), 1, fprof ) < 1)
break;
278 byte_counter += (2+nstack)*4;
279 progress = long(2.5*byte_counter * inv_total_bytes);
280 if ( progress > 100 ) progress = 100;
281 if ( step_progress < progress ) {
282 for ( ; step_progress <= progress; ++step_progress ) {
283 if ( ! (step_progress % 20) ) {
284 std::cout << step_progress <<
"%"; std::cout.flush();
285 }
else if ( ! (step_progress % 5) ) {
286 std::cout <<
'.'; std::cout.flush();
294 CallInfo_t caller_info( 0, stacktrace[nstack-1] );
300 for (
int i = nstack-1;
i > 0; --
i ) {
306 callee_info =
CallInfo_t( stacktrace[
i], stacktrace[
i-1] );
313 callee_info =
CallInfo_t( stacktrace[
i], stacktrace[0] );
319 callee_info.second = gMalloc;
342 }
else if (
i == 1 ) {
359 caller_info = callee_info;
366 for ( ; step_progress <= 100; ++step_progress ) {
367 if ( ! (step_progress % 20) ) {
368 std::cout << step_progress <<
"%"; std::cout.flush();
369 }
else if ( ! (step_progress % 5) ) {
370 std::cout <<
'.'; std::cout.flush();
373 std::cout <<
"]" << std::endl;
374 std::cout <<
"number of stacks: " << stack_counter << std::endl;
375 std::cout <<
"total alloc size: " << total_size << std::endl;
380 std::cout <<
"calculating sizes ... " << std::endl;
389 std::cout <<
"writing output to " <<
output <<
" ... (" <<
gCallTree.size() <<
" top level entries)" << std::endl;
391 std::ofstream fresult(
output.c_str() );
392 fresult <<
"events: memsize nallocs\n\n";
394 fresult <<
"fl=athena.cxx\nfn=athena\n0 0\n";
396 fresult <<
"cfn=" <<
getSymbol( icp->first.second ) <<
'\n';
397 fresult <<
"calls=" << icp->second.m_called <<
' ' << icp->first.second <<
'\n';
398 fresult << icp->first.first <<
' ' << icp->second.m_inclusive
399 <<
' ' << icp->second.m_called <<
'\n';
411 std::cout <<
"cross-check all calls: " <<
gTotalCalls << std::endl;
412 std::cout <<
"cross-check inclusive: " <<
gTotalIncl << std::endl;
413 std::cout <<
"cross-check-size (non-allocator): " <<
gTotalSize1 << std::endl;
414 std::cout <<
"cross-check-size (allocator): " <<
gTotalSize2 << std::endl;
428 std::string
input =
"hephaestus";
430 while ( (
opt = getopt(
argc,
argv,
"i:") ) != -1 ) {
444 glob( (
input +
"*.prof").c_str(), GLOB_DOOFFS, NULL, &globbuf );
446 std::cout <<
"files matching: " << globbuf.gl_pathc << std::endl;
447 for (
size_t ig = 0; ig < globbuf.gl_pathc; ++ig ) {
448 std::string
filename = globbuf.gl_pathv[ ig ];
449 std::string::size_type firstdot =
filename.find(
'.');
450 std::string evtnumber =
filename.substr( firstdot,
filename.rfind(
'.' )-firstdot );
454 globfree( &globbuf );