#include "bu/profiler.h" #include "bu/mutexlocker.h" #include "bu/sio.h" #include Bu::Profiler::Profiler() { } Bu::Profiler::~Profiler() { printReport(); } uint64_t Bu::Profiler::getMicroTime() { struct timeval tv; gettimeofday( &tv, NULL ); return ((uint64_t)tv.tv_sec)*1000000 + ((uint64_t)tv.tv_usec); } void Bu::Profiler::startEvent( const Bu::Blob &bName ) { Bu::MutexLocker l( mLock ); if( hEvent.has( bName ) ) { hEvent.get( bName ).append( Event() ); } else { hEvent.insert( bName, EventList( Event() ) ); } } void Bu::Profiler::endEvent( const Bu::Blob &bName ) { Bu::MutexLocker l( mLock ); if( !hEvent.has( bName ) ) return; if( hEvent.get( bName ).isEmpty() ) return; hEvent.get( bName ).last().end(); } void Bu::Profiler::printReport() const { class Breakdown { public: Breakdown( const Bu::Blob &bName ) : bName( bName ), uCount( 0 ), uTotal( 0 ), uMin( 0 ), uMax( 0 ) { } Breakdown( const Breakdown &rSrc ) : bName( rSrc.bName ), uCount( rSrc.uCount ), uTotal( rSrc.uTotal ), uMin( rSrc.uMin ), uMax( rSrc.uMax ) { } ~Breakdown() { } bool operator<( const Breakdown &rhs ) const { return uTotal > rhs.uTotal; } Breakdown &operator=( const Breakdown &rhs ) { bName = rhs.bName; uCount = rhs.uCount; uTotal = rhs.uTotal; uMin = rhs.uMin; uMax = rhs.uMax; return *this; } void add( uint64_t uSpan ) { if( uCount == 0 ) { uMin = uMax = uSpan; } else { if( uMin > uSpan ) uMin = uSpan; if( uMax < uSpan ) uMax = uSpan; } uCount++; uTotal += uSpan; } Bu::Blob bName; uint64_t uCount; uint64_t uTotal; uint64_t uMin; uint64_t uMax; }; Bu::MutexLocker l( mLock ); int iTitleLen = 0; Bu::List lBreakdown; for( EventListHash::const_iterator iType = hEvent.begin(); iType; iType++ ) { Breakdown b( iType.getKey() ); if( iTitleLen < b.bName.getSize() ) iTitleLen = b.bName.getSize(); for( EventList::const_iterator iEv = iType.getValue().begin(); iEv; iEv++ ) { b.add( (*iEv).getSpan() ); } lBreakdown.append( b ); } lBreakdown.sort(); Bu::println("%1 %2 %3 %4 %5 %6") .arg("Title", Bu::Fmt(iTitleLen) ) .arg("Cnt", Bu::Fmt(5) ) .arg("Total", Bu::Fmt(9) ) .arg("Avg", Bu::Fmt(9) ) .arg("Max", Bu::Fmt(9) ) .arg("Min", Bu::Fmt(9) ); for( Bu::List::iterator i = lBreakdown.begin(); i; i++ ) { Bu::println("%1 %2 %3.%4 %5.%6 %7.%8 %9.%10") .arg( (*i).bName.getData(), Bu::Fmt(iTitleLen) ) .arg( (*i).uCount, Bu::Fmt(5) ) .arg( ((*i).uTotal/1000000), Bu::Fmt(5).right() ) .arg( ((*i).uTotal/1000)%1000, Bu::Fmt(3).fill('0').right() ) .arg( ((*i).uTotal/(*i).uCount)/1000000, Bu::Fmt(5).right() ) .arg( (((*i).uTotal/(*i).uCount)/1000)%1000, Bu::Fmt(3).right().fill('0') ) .arg( (*i).uMax/1000000, Bu::Fmt(5).right() ) .arg( ((*i).uMax/1000)%1000, Bu::Fmt(3).right().fill('0') ) .arg( (*i).uMin/1000000, Bu::Fmt(5).right() ) .arg( ((*i).uMin/1000)%1000, Bu::Fmt(3).right().fill('0') ) ; } } Bu::Profiler::Event::Event() : iStart( Bu::Profiler::getMicroTime() ), iStop( 0 ) { } Bu::Profiler::Event::Event( const Event &rSrc ) : iStart( rSrc.iStart ), iStop( rSrc.iStop ) { } Bu::Profiler::Event::~Event() { } void Bu::Profiler::Event::end() { if( iStop == 0 ) iStop = Bu::Profiler::getMicroTime(); } bool Bu::Profiler::Event::hasEnded() const { return iStop != 0; } uint64_t Bu::Profiler::Event::getStart() const { return iStart; } uint64_t Bu::Profiler::Event::getEnd() const { return iStop; } uint64_t Bu::Profiler::Event::getSpan() const { if( iStop < iStart ) return 0; return iStop-iStart; }