#include "externals.hh" #include "utilities.hh" #include "profiling.hh" #include #include T_Profiler T_Profiler::Profiler; constexpr uint32_t T_Profiler::Samples; constexpr uint32_t T_Profiler::History; constexpr uint32_t T_Profiler::Invalid; void T_Profiler::clear( ) { sections_.clear( ); samples_.clear( ); starts_.clear( ); } void T_Profiler::startFrame( ) { previous_ = Invalid; current_ = Invalid; } void T_Profiler::endFrame( ) { const auto n( sections_.size( ) ); while ( secDurations_.size( ) < n ) { secDurations_.push_back( 0 ); secStarts_.push_back( 0 ); } for ( auto i = 0u ; i < n ; i ++ ) { const float d = computeDuration( i ); secDurations_[ i ] = d; if ( parents_[ i ] != Invalid ) { assert( parents_[ i ] < i ); secStarts_[ i ] = secStarts_[ parents_[ i ] ]; } else if ( chain_[ i ] != Invalid ) { assert( chain_[ i ] < i ); secStarts_[ i ] = secStarts_[ chain_[ i ] ] + secDurations_[ chain_[ i ] ]; } else { secStarts_[ i ] = 0; } } } void T_Profiler::start( __rd__ std::string const& section ) { const auto n( sections_.size( ) ); const auto pos( find( section ) ); if ( pos == n ) { sections_.push_back( section ); samples_.push_back( T_SamplesList_{ } ); starts_.push_back( 0u ); chain_.push_back( Invalid ); parents_.push_back( Invalid ); } chain_[ pos ] = previous_; if ( current_ != Invalid ) { parents_[ pos ] = current_; previous_ = Invalid; } else { parents_[ pos ] = Invalid; } current_ = pos; struct timespec ts; clock_gettime( CLOCK_MONOTONIC , &ts ); starts_[ pos ] = ts.tv_sec * 1000000000 + ts.tv_nsec; } void T_Profiler::end( __rd__ std::string const& section ) { const auto pos( find( section ) ); const auto n( sections_.size( ) ); if ( pos == n ) { return; } struct timespec ts; clock_gettime( CLOCK_MONOTONIC , &ts ); const uint64_t ended = ts.tv_sec * 1000000000 + ts.tv_nsec; const uint64_t duration = ended - starts_[ pos ]; auto& samples( samples_[ pos ] ); if ( samples.size( ) == 0 || ( samples.size( ) < History && samples[ 0 ].nSamples == Samples ) ) { samples.insert( samples.begin( ) , T_ProfilerSamples{ 0 , 0 } ); } else if ( samples.size( ) == History && samples[ 0 ].nSamples == Samples ) { for ( auto i = 1u ; i < History ; i ++ ) { samples[ i ] = samples[ i - 1 ]; } samples[ 0 ].sum = 0; samples[ 0 ].nSamples = 0; } samples[ 0 ].sum += float( duration ) * 1e-6; samples[ 0 ].nSamples ++; previous_ = pos; current_ = Invalid; } float T_Profiler::computeDuration( __rd__ const uint32_t section ) const { auto const& samples( samples_[ section ] ); float total = 0; float nSamples = 0; for ( auto const& entry : samples ) { total += entry.sum; nSamples += entry.nSamples; } return total / nSamples; } uint32_t T_Profiler::find( __rd__ std::string const& section ) const { const auto n( sections_.size( ) ); auto pos( 0u ); while ( pos < n && sections_[ pos ] != section ) { pos ++; } return pos; }