diff options
Diffstat (limited to 'indra/llcommon')
| -rwxr-xr-x | indra/llcommon/llfasttimer.cpp | 4 | ||||
| -rw-r--r-- | indra/llcommon/lltraceaccumulators.cpp | 146 | ||||
| -rw-r--r-- | indra/llcommon/lltraceaccumulators.h | 291 | ||||
| -rw-r--r-- | indra/llcommon/lltracerecording.cpp | 42 | ||||
| -rw-r--r-- | indra/llcommon/lltracerecording.h | 2 | 
5 files changed, 267 insertions, 218 deletions
| diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index f4c87ab6f6..3b17b6022c 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -431,11 +431,11 @@ TimeBlockAccumulator::TimeBlockAccumulator()  	mParent(NULL)  {} -void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, bool append ) +void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, EBufferAppendType append_type )  {  	// we can't merge two unrelated time block samples, as that will screw with the nested timings  	// due to the call hierarchy of each thread -	llassert(append); +	llassert(append_type == SEQUENTIAL);  	mTotalTimeCounter += other.mTotalTimeCounter - other.mStartTotalTimeCounter;  	mSelfTimeCounter += other.mSelfTimeCounter;  	mCalls += other.mCalls; diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp index 950c1d97d1..a632f5634c 100644 --- a/indra/llcommon/lltraceaccumulators.cpp +++ b/indra/llcommon/lltraceaccumulators.cpp @@ -86,21 +86,21 @@ bool AccumulatorBufferGroup::isPrimary() const  void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other )  { -	mCounts.addSamples(other.mCounts); -	mSamples.addSamples(other.mSamples); -	mEvents.addSamples(other.mEvents); -	mMemStats.addSamples(other.mMemStats); -	mStackTimers.addSamples(other.mStackTimers); +	mCounts.addSamples(other.mCounts, SEQUENTIAL); +	mSamples.addSamples(other.mSamples, SEQUENTIAL); +	mEvents.addSamples(other.mEvents, SEQUENTIAL); +	mMemStats.addSamples(other.mMemStats, SEQUENTIAL); +	mStackTimers.addSamples(other.mStackTimers, SEQUENTIAL);  }  void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other)  { -	mCounts.addSamples(other.mCounts, false); -	mSamples.addSamples(other.mSamples, false); -	mEvents.addSamples(other.mEvents, false); -	mMemStats.addSamples(other.mMemStats, false); +	mCounts.addSamples(other.mCounts, NON_SEQUENTIAL); +	mSamples.addSamples(other.mSamples, NON_SEQUENTIAL); +	mEvents.addSamples(other.mEvents, NON_SEQUENTIAL); +	mMemStats.addSamples(other.mMemStats, NON_SEQUENTIAL);  	// for now, hold out timers from merge, need to be displayed per thread -	//mStackTimers.addSamples(other.mStackTimers, false); +	//mStackTimers.addSamples(other.mStackTimers, NON_SEQUENTIAL);  }  void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other) @@ -120,4 +120,130 @@ void AccumulatorBufferGroup::sync()  	mMemStats.sync(time_stamp);  } +void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type ) +{ +	if (!mHasValue) +	{ +		*this = other; + +		if (append_type == NON_SEQUENTIAL) +		{ +			// restore own last value state +			mLastValue = NaN; +			mHasValue = false; +		} +	} +	else if (other.mHasValue) +	{ +		mSum += other.mSum; + +		if (other.mMin < mMin) { mMin = other.mMin; } +		if (other.mMax > mMax) { mMax = other.mMax; } + +		F64 epsilon = 0.0000001; + +		if (other.mTotalSamplingTime > epsilon) +		{ +			// combine variance (and hence standard deviation) of 2 different sized sample groups using +			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm +			F64 n_1 = mTotalSamplingTime, +				n_2 = other.mTotalSamplingTime; +			F64 m_1 = mMean, +				m_2 = other.mMean; +			F64 v_1 = mSumOfSquares / mTotalSamplingTime, +				v_2 = other.mSumOfSquares / other.mTotalSamplingTime; +			if (n_1 < epsilon) +			{ +				mSumOfSquares = other.mSumOfSquares; +			} +			else +			{ +				mSumOfSquares =	mTotalSamplingTime +					* ((((n_1 - epsilon) * v_1) +					+ ((n_2 - epsilon) * v_2) +					+ (((n_1 * n_2) / (n_1 + n_2)) +					* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2)))) +					/ (n_1 + n_2 - epsilon)); +			} + +			llassert(other.mTotalSamplingTime > 0); +			F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime); +			mNumSamples += other.mNumSamples; +			mTotalSamplingTime += other.mTotalSamplingTime; +			mMean = (mMean * weight) + (other.mMean * (1.0 - weight)); +		} +		if (append_type == SEQUENTIAL) +		{ +			mLastValue = other.mLastValue; +			mLastSampleTimeStamp = other.mLastSampleTimeStamp; +			mHasValue = true; +		} +	} +} + +void SampleAccumulator::reset( const SampleAccumulator* other ) +{ +	mLastValue = other ? other->mLastValue : NaN; +	mHasValue = other ? other->mHasValue : false; +	mNumSamples = 0; +	mSum = 0; +	mMin = mLastValue; +	mMax = mLastValue; +	mMean = mLastValue; +	mSumOfSquares = 0; +	mLastSampleTimeStamp = LLTimer::getTotalSeconds(); +	mTotalSamplingTime = 0; +} + +void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendType append_type ) +{ +	if (other.mNumSamples) +	{ +		if (!mNumSamples) +		{ +			*this = other; +		} +		else +		{ +			mSum += other.mSum; + +			// NOTE: both conditions will hold first time through +			if (other.mMin < mMin) { mMin = other.mMin; } +			if (other.mMax > mMax) { mMax = other.mMax; } + +			// combine variance (and hence standard deviation) of 2 different sized sample groups using +			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm +			F64 n_1 = (F64)mNumSamples, +				n_2 = (F64)other.mNumSamples; +			F64 m_1 = mMean, +				m_2 = other.mMean; +			F64 v_1 = mSumOfSquares / mNumSamples, +				v_2 = other.mSumOfSquares / other.mNumSamples; +			mSumOfSquares = (F64)mNumSamples +				* ((((n_1 - 1.f) * v_1) +				+ ((n_2 - 1.f) * v_2) +				+ (((n_1 * n_2) / (n_1 + n_2)) +				* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2)))) +				/ (n_1 + n_2 - 1.f)); + +			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples); +			mNumSamples += other.mNumSamples; +			mMean = mMean * weight + other.mMean * (1.f - weight); +			if (append_type == SEQUENTIAL) mLastValue = other.mLastValue; +		} +	} +} + +void EventAccumulator::reset( const EventAccumulator* other ) +{ +	mNumSamples = 0; +	mSum = NaN; +	mMin = NaN; +	mMax = NaN; +	mMean = NaN; +	mSumOfSquares = 0; +	mLastValue = other ? other->mLastValue : NaN; +} + +  } diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h index 9ea787188c..5871dc4bea 100644 --- a/indra/llcommon/lltraceaccumulators.h +++ b/indra/llcommon/lltraceaccumulators.h @@ -38,6 +38,14 @@  namespace LLTrace  { +	const F64 NaN	= std::numeric_limits<double>::quiet_NaN(); + +	enum EBufferAppendType +	{ +		SEQUENTIAL, +		NON_SEQUENTIAL +	}; +  	template<typename ACCUMULATOR>  	class AccumulatorBuffer : public LLRefCount  	{ @@ -83,12 +91,12 @@ namespace LLTrace  			return mStorage[index];   		} -		void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, bool append = true) +		void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, EBufferAppendType append_type)  		{  			llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);  			for (size_t i = 0; i < sNextStorageSlot; i++)  			{ -				mStorage[i].addSamples(other.mStorage[i], append); +				mStorage[i].addSamples(other.mStorage[i], append_type);  			}  		} @@ -211,7 +219,6 @@ namespace LLTrace  	template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;  	template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL; -  	class EventAccumulator  	{  	public: @@ -219,98 +226,51 @@ namespace LLTrace  		typedef F64 mean_t;  		EventAccumulator() -		:	mSum(0), -			mMin((std::numeric_limits<F64>::max)()), -			mMax((std::numeric_limits<F64>::min)()), -			mMean(0), +		:	mSum(NaN), +			mMin(NaN), +			mMax(NaN), +			mMean(NaN),  			mSumOfSquares(0),  			mNumSamples(0), -			mLastValue(0) +			mLastValue(NaN)  		{}  		void record(F64 value)  		{ -			mNumSamples++; -			mSum += value; -			// NOTE: both conditions will hold on first pass through -			if (value < mMin) +			if (mNumSamples == 0)  			{ +				mSum = value; +				mMean = value;  				mMin = value; -			} -			if (value > mMax) -			{  				mMax = value;  			} -			F64 old_mean = mMean; -			mMean += (value - old_mean) / (F64)mNumSamples; -			mSumOfSquares += (value - old_mean) * (value - mMean); -			mLastValue = value; -		} - -		void addSamples(const EventAccumulator& other, bool append) -		{ -			if (other.mNumSamples) +			else  			{ -				mSum += other.mSum; - -				// NOTE: both conditions will hold first time through -				if (other.mMin < mMin) { mMin = other.mMin; } -				if (other.mMax > mMax) { mMax = other.mMax; } - -				// combine variance (and hence standard deviation) of 2 different sized sample groups using -				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm -				F64 n_1 = (F64)mNumSamples, -					n_2 = (F64)other.mNumSamples; -				F64 m_1 = mMean, -					m_2 = other.mMean; -				F64 v_1 = mSumOfSquares / mNumSamples, -					v_2 = other.mSumOfSquares / other.mNumSamples; -				if (n_1 == 0) -				{ -					mSumOfSquares = other.mSumOfSquares; -				} -				else if (n_2 == 0) -				{ -					// don't touch variance -					// mSumOfSquares = mSumOfSquares; -				} -				else -				{ -					mSumOfSquares = (F64)mNumSamples -						* ((((n_1 - 1.f) * v_1) -						+ ((n_2 - 1.f) * v_2) -						+ (((n_1 * n_2) / (n_1 + n_2)) -						* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2)))) -						/ (n_1 + n_2 - 1.f)); -				} +				mSum += value; +				F64 old_mean = mMean; +				mMean += (value - old_mean) / (F64)mNumSamples; +				mSumOfSquares += (value - old_mean) * (value - mMean); -				F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples); -				mNumSamples += other.mNumSamples; -				mMean = mMean * weight + other.mMean * (1.f - weight); -				if (append) mLastValue = other.mLastValue; +				if (value < mMin) { mMin = value; } +				else if (value > mMax) { mMax = value; }  			} -		} -		void reset(const EventAccumulator* other) -		{ -			mNumSamples = 0; -			mSum = 0; -			mMin = std::numeric_limits<F64>::max(); -			mMax = std::numeric_limits<F64>::min(); -			mMean = 0; -			mSumOfSquares = 0; -			mLastValue = other ? other->mLastValue : 0; +			mNumSamples++; +			mLastValue = value;  		} +		void addSamples(const EventAccumulator& other, EBufferAppendType append_type); +		void reset(const EventAccumulator* other);  		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {} -		F64	getSum() const { return mSum; } -		F64	getMin() const { return mMin; } -		F64	getMax() const { return mMax; } -		F64	getLastValue() const { return mLastValue; } -		F64	getMean() const { return mMean; } +		F64	getSum() const               { return mSum; } +		F64	getMin() const               { return mMin; } +		F64	getMax() const               { return mMax; } +		F64	getLastValue() const         { return mLastValue; } +		F64	getMean() const              { return mMean; }  		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); } -		U32 getSampleCount() const { return mNumSamples; } +		U32 getSampleCount() const       { return mNumSamples; } +		bool hasValue() const			 { return mNumSamples > 0; }  	private:  		F64	mSum, @@ -333,143 +293,85 @@ namespace LLTrace  		SampleAccumulator()  		:	mSum(0), -			mMin((std::numeric_limits<F64>::max)()), -			mMax((std::numeric_limits<F64>::min)()), -			mMean(0), +			mMin(NaN), +			mMax(NaN), +			mMean(NaN),  			mSumOfSquares(0), -			mLastSampleTimeStamp(LLTimer::getTotalSeconds()), +			mLastSampleTimeStamp(0),  			mTotalSamplingTime(0),  			mNumSamples(0), -			mLastValue(0), +			mLastValue(NaN),  			mHasValue(false)  		{}  		void sample(F64 value)  		{  			LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds(); -			LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp; -			mLastSampleTimeStamp = time_stamp; -			if (mHasValue) +			// store effect of last value +			sync(time_stamp); + +			if (!mHasValue)  			{ -				mTotalSamplingTime += delta_time; -				mSum += mLastValue * delta_time; +				mHasValue = true; -				// NOTE: both conditions will hold first time through +				mMin = value; +				mMax = value; +				mMean = value; +				mLastSampleTimeStamp = time_stamp; +			} +			else +			{  				if (value < mMin) { mMin = value; } -				if (value > mMax) { mMax = value; } - -				F64 old_mean = mMean; -				mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean); -				mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean); +				else if (value > mMax) { mMax = value; }  			}  			mLastValue = value;  			mNumSamples++; -			mHasValue = true;  		} -		void addSamples(const SampleAccumulator& other, bool append) -		{ -			if (other.mTotalSamplingTime) -			{ -				mSum += other.mSum; - -				// NOTE: both conditions will hold first time through -				if (other.mMin < mMin) { mMin = other.mMin; } -				if (other.mMax > mMax) { mMax = other.mMax; } - -				// combine variance (and hence standard deviation) of 2 different sized sample groups using -				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm -				F64 n_1 = mTotalSamplingTime, -					n_2 = other.mTotalSamplingTime; -				F64 m_1 = mMean, -					m_2 = other.mMean; -				F64 v_1 = mSumOfSquares / mTotalSamplingTime, -					v_2 = other.mSumOfSquares / other.mTotalSamplingTime; -				if (n_1 == 0) -				{ -					mSumOfSquares = other.mSumOfSquares; -				} -				else if (n_2 == 0) -				{ -					// variance is unchanged -					// mSumOfSquares = mSumOfSquares; -				} -				else -				{ -					mSumOfSquares =	mTotalSamplingTime -						* ((((n_1 - 1.f) * v_1) -						+ ((n_2 - 1.f) * v_2) -						+ (((n_1 * n_2) / (n_1 + n_2)) -						* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2)))) -						/ (n_1 + n_2 - 1.f)); -				} - -				llassert(other.mTotalSamplingTime > 0); -				F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime); -				mNumSamples += other.mNumSamples; -				mTotalSamplingTime += other.mTotalSamplingTime; -				mMean = (mMean * weight) + (other.mMean * (1.0 - weight)); -				if (append) -				{ -					mLastValue = other.mLastValue; -					mLastSampleTimeStamp = other.mLastSampleTimeStamp; -					mHasValue |= other.mHasValue; -				} -			} -		} - -		void reset(const SampleAccumulator* other) -		{ -			mNumSamples = 0; -			mSum = 0; -			mMin = std::numeric_limits<F64>::max(); -			mMax = std::numeric_limits<F64>::min(); -			mMean = other ? other->mLastValue : 0; -			mSumOfSquares = 0; -			mLastSampleTimeStamp = LLTimer::getTotalSeconds(); -			mTotalSamplingTime = 0; -			mLastValue = other ? other->mLastValue : 0; -			mHasValue = other ? other->mHasValue : false; -		} +		void addSamples(const SampleAccumulator& other, EBufferAppendType append_type); +		void reset(const SampleAccumulator* other);  		void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)  		{ -			LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp; -  			if (mHasValue)  			{ +				LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;  				mSum += mLastValue * delta_time;  				mTotalSamplingTime += delta_time; +				F64 old_mean = mMean; +				mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean); +				mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);  			}  			mLastSampleTimeStamp = time_stamp;  		} -		F64	getSum() const { return mSum; } -		F64	getMin() const { return mMin; } -		F64	getMax() const { return mMax; } -		F64	getLastValue() const { return mLastValue; } -		F64	getMean() const { return mMean; } +		F64	getSum() const               { return mSum; } +		F64	getMin() const               { return mMin; } +		F64	getMax() const               { return mMax; } +		F64	getLastValue() const         { return mLastValue; } +		F64	getMean() const              { return mMean; }  		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); } -		U32 getSampleCount() const { return mNumSamples; } -		bool hasValue() const { return mHasValue; } +		U32 getSampleCount() const       { return mNumSamples; } +		bool hasValue() const            { return mHasValue; }  	private: -		F64	mSum, -			mMin, -			mMax, -			mLastValue; +		F64		mSum, +				mMin, +				mMax, +				mLastValue; -		bool mHasValue; +		bool	mHasValue;		// distinct from mNumSamples, since we might have inherited an old sample -		F64	mMean, -			mSumOfSquares; +		F64		mMean, +				mSumOfSquares; -		LLUnitImplicit<F64, LLUnits::Seconds>	mLastSampleTimeStamp, -			mTotalSamplingTime; +		LLUnitImplicit<F64, LLUnits::Seconds>	 +				mLastSampleTimeStamp, +				mTotalSamplingTime; -		U32	mNumSamples; +		U32		mNumSamples;  	};  	class CountAccumulator @@ -489,7 +391,7 @@ namespace LLTrace  			mSum += value;  		} -		void addSamples(const CountAccumulator& other, bool /*append*/) +		void addSamples(const CountAccumulator& other, bool /*follows_in_sequence*/)  		{  			mSum += other.mSum;  			mNumSamples += other.mNumSamples; @@ -534,25 +436,26 @@ namespace LLTrace  		};  		TimeBlockAccumulator(); -		void addSamples(const self_t& other, bool /*append*/); +		void addSamples(const self_t& other, EBufferAppendType append_type);  		void reset(const self_t* other);  		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}  		//  		// members  		// -		U64							mStartTotalTimeCounter, -			mTotalTimeCounter, -			mSelfTimeCounter; -		U32							mCalls; -		class TimeBlock*			mParent;		// last acknowledged parent of this time block -		class TimeBlock*			mLastCaller;	// used to bootstrap tree construction -		U16							mActiveCount;	// number of timers with this ID active on stack -		bool						mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame +		U64					mStartTotalTimeCounter, +							mTotalTimeCounter, +							mSelfTimeCounter; +		U32					mCalls; +		class TimeBlock*	mParent;		// last acknowledged parent of this time block +		class TimeBlock*	mLastCaller;	// used to bootstrap tree construction +		U16					mActiveCount;	// number of timers with this ID active on stack +		bool				mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame  	};  	class TimeBlock; +  	class TimeBlockTreeNode  	{  	public: @@ -603,10 +506,10 @@ namespace LLTrace  			mDeallocatedCount(0)  		{} -		void addSamples(const MemStatAccumulator& other, bool append) +		void addSamples(const MemStatAccumulator& other, EBufferAppendType append_type)  		{ -			mSize.addSamples(other.mSize, append); -			mChildSize.addSamples(other.mChildSize, append); +			mSize.addSamples(other.mSize, append_type); +			mChildSize.addSamples(other.mChildSize, append_type);  			mAllocatedCount += other.mAllocatedCount;  			mDeallocatedCount += other.mDeallocatedCount;  		} @@ -645,11 +548,11 @@ namespace LLTrace  		void reset(AccumulatorBufferGroup* other = NULL);  		void sync(); -		AccumulatorBuffer<CountAccumulator>	 			mCounts; -		AccumulatorBuffer<SampleAccumulator>			mSamples; -		AccumulatorBuffer<EventAccumulator>				mEvents; -		AccumulatorBuffer<TimeBlockAccumulator> 		mStackTimers; -		AccumulatorBuffer<MemStatAccumulator> 			mMemStats; +		AccumulatorBuffer<CountAccumulator>	 	mCounts; +		AccumulatorBuffer<SampleAccumulator>	mSamples; +		AccumulatorBuffer<EventAccumulator>		mEvents; +		AccumulatorBuffer<TimeBlockAccumulator> mStackTimers; +		AccumulatorBuffer<MemStatAccumulator> 	mMemStats;  	};  } diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index 9fce6c11cc..a4d58d8ab1 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -287,6 +287,11 @@ U32 Recording::getSampleCount( const TraceType<SampleAccumulator>& stat )  	return mBuffers->mSamples[stat.getIndex()].getSampleCount();  } +bool Recording::hasValue(const TraceType<EventAccumulator>& stat) +{ +	return mBuffers->mEvents[stat.getIndex()].hasValue(); +} +  F64 Recording::getMin( const TraceType<EventAccumulator>& stat )  {  	return mBuffers->mEvents[stat.getIndex()].getMin(); @@ -531,10 +536,12 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, s  	for (S32 i = 1; i <= num_periods; i++)  	{  		S32 index = (mCurPeriod + total_periods - i) % total_periods; -		if (mRecordingPeriods[index].getDuration() > 0.f) +		Recording& recording = mRecordingPeriods[index]; + +		if (recording.hasValue(stat))  		{ -			S32 period_sample_count = mRecordingPeriods[index].getSampleCount(stat); -			mean += mRecordingPeriods[index].getMean(stat) * period_sample_count; +			S32 period_sample_count = recording.getSampleCount(stat); +			mean += recording.getMean(stat) * period_sample_count;  			total_sample_count += period_sample_count;  		}  	} @@ -555,7 +562,11 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, si  	for (S32 i = 1; i <= num_periods; i++)  	{  		S32 index = (mCurPeriod + total_periods - i) % total_periods; -		min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat)); +		Recording& recording = mRecordingPeriods[index]; +		if (recording.hasValue(stat)) +		{ +			min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat)); +		}  	}  	return min_val;  } @@ -569,7 +580,11 @@ F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, si  	for (S32 i = 1; i <= num_periods; i++)  	{  		S32 index = (mCurPeriod + total_periods - i) % total_periods; -		max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat)); +		Recording& recording = mRecordingPeriods[index]; +		if (recording.hasValue(stat)) +		{ +			max_val = llmax(max_val, recording.getMax(stat)); +		}  	}  	return max_val;  } @@ -583,9 +598,10 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, s  	for (S32 i = 1; i <= num_periods; i++)  	{  		S32 index = (mCurPeriod + total_periods - i) % total_periods; -		if (mRecordingPeriods[index].hasValue(stat)) +		Recording& recording = mRecordingPeriods[index]; +		if (recording.hasValue(stat))  		{ -			min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat)); +			min_val = llmin(min_val, recording.getMin(stat));  		}  	}  	return min_val; @@ -600,9 +616,10 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, si  	for (S32 i = 1; i <= num_periods; i++)  	{  		S32 index = (mCurPeriod + total_periods - i) % total_periods; -		if (mRecordingPeriods[index].hasValue(stat)) +		Recording& recording = mRecordingPeriods[index]; +		if (recording.hasValue(stat))  		{ -			max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat)); +			max_val = llmax(max_val, recording.getMax(stat));  		}  	}  	return max_val; @@ -622,10 +639,11 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,  	for (S32 i = 1; i <= num_periods; i++)  	{  		S32 index = (mCurPeriod + total_periods - i) % total_periods; -		if (mRecordingPeriods[index].getDuration() > 0.f && mRecordingPeriods[index].hasValue(stat)) +		Recording& recording = mRecordingPeriods[index]; +		if (recording.hasValue(stat))  		{ -			LLUnit<F64, LLUnits::Seconds> recording_duration = mRecordingPeriods[index].getDuration(); -			mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value(); +			LLUnit<F64, LLUnits::Seconds> recording_duration = recording.getDuration(); +			mean += recording.getMean(stat) * recording_duration.value();  			total_duration += recording_duration;  		}  	} diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 51b411b7bd..7ee8aba874 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -248,6 +248,8 @@ namespace LLTrace  		U32 getSampleCount(const TraceType<SampleAccumulator>& stat);  		// EventStatHandle accessors +		bool hasValue(const TraceType<EventAccumulator>& stat); +  		F64 getSum(const TraceType<EventAccumulator>& stat);  		template <typename T>  		typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat) | 
