#include "bu/speedometer.h" #include "bu/mutexlocker.h" #include "bu/sio.h" #include #include Bu::Speedometer::Speedometer( int64_t iBucketMs, int32_t iBucketCount ) : aiBucket( NULL ), iTotal( 0 ), iCapacity( iBucketCount ), iFill( 0 ), iStart( 0 ), iCurrent( 0 ), iBucketMs( iBucketMs ), iStartTime( -1 ), iWindowSizeMs( iBucketMs*iBucketCount ), iLastUpdate( -1 ) { aiBucket = new uint32_t[iCapacity]; memset( aiBucket, 0, sizeof(uint32_t)*iCapacity ); } Bu::Speedometer::~Speedometer() { delete[] aiBucket; aiBucket = NULL; } void Bu::Speedometer::addEvent() { Bu::MutexLocker l( mLock ); int64_t iNow = getCurrentTime(); _updateBuckets( iNow ); if( iStartTime < 0 ) { iStartTime = iNow; iFill = 1; aiBucket[iCurrent] = 1; iTotal = 1; } else { aiBucket[iCurrent]++; iTotal++; } iLastUpdate = iNow; } void Bu::Speedometer::debug() { Bu::MutexLocker l( mLock ); Bu::print("%1 of %2: %3:%4: "). arg( iFill ).arg( iCapacity ).arg( iStart ).arg( iCurrent ); for( int j = 0; j < iFill; j++ ) { Bu::print("%1 | ").arg( aiBucket[(j+iStart)%iCapacity] ); } Bu::println(" total = %1").arg( iTotal ); } void Bu::Speedometer::_updateBuckets( int64_t iNow ) { if( iNow > iLastUpdate+iWindowSizeMs ) { iLastUpdate = iStartTime = -1; iFill = 0; iStart = iCurrent = 0; aiBucket[iCurrent] = 0; iTotal = 0; } else { int64_t iSkip = (iNow-(iStartTime+iBucketMs*iFill)); if( iSkip < 0 ) return; iSkip = (iSkip/iBucketMs) + ((iSkip%iBucketMs)?(1):(0)); for( int64_t j = 0; j < iSkip; j++ ) { iCurrent = (iCurrent+1)%iCapacity; if( iFill < iCapacity ) { iFill++; } else { iTotal -= aiBucket[iStart]; aiBucket[iStart] = 0; iStart = (iStart+1)%iCapacity; iStartTime += iBucketMs; } } } } double Bu::Speedometer::getSpeed() { Bu::MutexLocker l( mLock ); _updateBuckets( getCurrentTime() ); if( iStartTime < 0 ) return 0.0; return (double)iTotal / (double)(iFill*iBucketMs); } int32_t Bu::Speedometer::getTotalEvents() { Bu::MutexLocker l( mLock ); return iTotal; } int64_t Bu::Speedometer::getCurrentTime() const { struct timeval tv; gettimeofday( &tv, NULL ); return tv.tv_sec*1000 + tv.tv_usec/1000; }