fixed things so that trace recordings can be read from even while active

master
Richard Linden 2013-10-21 14:22:21 -07:00
parent 54c9aba3d9
commit 1dfba44b3d
7 changed files with 299 additions and 102 deletions

View File

@ -155,6 +155,39 @@ void AccumulatorBufferGroup::sync()
}
}
F64 SampleAccumulator::mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b)
{
const F64 epsilon = 0.0000001;
if (a.getSamplingTime() > epsilon && b.getSamplingTime() > 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 = a.getSamplingTime(),
n_2 = b.getSamplingTime();
F64 m_1 = a.getMean(),
m_2 = b.getMean();
F64 v_1 = a.getSumOfSquares() / a.getSamplingTime(),
v_2 = b.getSumOfSquares() / b.getSamplingTime();
if (n_1 < epsilon)
{
return b.getSumOfSquares();
}
else
{
return a.getSamplingTime()
* ((((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));
}
}
return a.getSumOfSquares();
}
void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type )
{
if (append_type == NON_SEQUENTIAL)
@ -180,37 +213,8 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
if (other.mMin < mMin) { mMin = other.mMin; }
if (other.mMax > mMax) { mMax = other.mMax; }
F64 epsilon = 0.0000001;
mSumOfSquares = mergeSumsOfSquares(*this, other);
if (other.mTotalSamplingTime > epsilon && 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));
}
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;
@ -234,6 +238,29 @@ void SampleAccumulator::reset( const SampleAccumulator* other )
mTotalSamplingTime = 0;
}
F64 EventAccumulator::mergeSumsOfSquares(const EventAccumulator& a, const EventAccumulator& b)
{
if (a.mNumSamples && b.mNumSamples)
{
// 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 = a.mNumSamples,
n_2 = b.mNumSamples;
F64 m_1 = a.mMean,
m_2 = b.mMean;
F64 v_1 = a.mSumOfSquares / a.mNumSamples,
v_2 = b.mSumOfSquares / b.mNumSamples;
return (F64)a.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));
}
return a.mSumOfSquares;
}
void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendType append_type )
{
if (other.mNumSamples)
@ -250,20 +277,7 @@ void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendT
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));
mSumOfSquares = mergeSumsOfSquares(*this, other);
F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
mNumSamples += other.mNumSamples;

View File

@ -276,6 +276,9 @@ namespace LLTrace
S32 getSampleCount() const { return mNumSamples; }
bool hasValue() const { return mNumSamples > 0; }
// helper utility to calculate combined sumofsquares total
static F64 mergeSumsOfSquares(const EventAccumulator& a, const EventAccumulator& b);
private:
F64 mSum,
mLastValue;
@ -359,10 +362,13 @@ namespace LLTrace
F64 getMean() const { return mMean; }
F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
F64 getSumOfSquares() const { return mSumOfSquares; }
F64SecondsImplicit getSamplingTime() { return mTotalSamplingTime; }
F64SecondsImplicit getSamplingTime() const { return mTotalSamplingTime; }
S32 getSampleCount() const { return mNumSamples; }
bool hasValue() const { return mHasValue; }
// helper utility to calculate combined sumofsquares total
static F64 mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b);
private:
F64 mSum,
mLastValue;

View File

@ -32,6 +32,11 @@
#include "lltracethreadrecorder.h"
#include "llthread.h"
inline F64 lerp(F64 a, F64 b, F64 u)
{
return a + ((b - a) * u);
}
namespace LLTrace
{
@ -43,7 +48,7 @@ extern MemStatHandle gTraceMemStat;
Recording::Recording(EPlayState state)
: mElapsedSeconds(0),
mInHandOff(false)
mActiveBuffers(NULL)
{
claim_alloc(gTraceMemStat, this);
mBuffers = new AccumulatorBufferGroup();
@ -88,13 +93,20 @@ Recording::~Recording()
}
}
// brings recording to front of recorder stack, with up to date info
void Recording::update()
{
if (isStarted())
{
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
AccumulatorBufferGroup* buffers = mBuffers.write();
LLTrace::get_thread_recorder()->bringUpToDate(buffers);
llassert(mActiveBuffers);
if(!mActiveBuffers->isCurrent())
{
AccumulatorBufferGroup* buffers = mBuffers.write();
LLTrace::get_thread_recorder()->deactivate(buffers);
mActiveBuffers = LLTrace::get_thread_recorder()->activate(buffers);
}
mSamplingTimer.reset();
}
@ -112,20 +124,19 @@ void Recording::handleStart()
{
mSamplingTimer.reset();
mBuffers.setStayUnique(true);
LLTrace::get_thread_recorder()->activate(mBuffers.write(), mInHandOff);
mInHandOff = false;
mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write());
}
void Recording::handleStop()
{
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
mActiveBuffers = NULL;
mBuffers.setStayUnique(false);
}
void Recording::handleSplitTo(Recording& other)
{
other.mInHandOff = true;
mBuffers.write()->handOffTo(*other.mBuffers.write());
}
@ -139,214 +150,378 @@ void Recording::appendRecording( Recording& other )
bool Recording::hasValue(const StatType<TimeBlockAccumulator>& stat)
{
return mBuffers->mStackTimers[stat.getIndex()].hasValue();
update();
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
}
F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
{
update();
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
return F64Seconds((F64)(accumulator.mTotalTimeCounter)
/ (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
return F64Seconds((F64)(accumulator.mTotalTimeCounter) + (F64)(active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
/ (F64)LLTrace::BlockTimerStatHandle::countsPerSecond();
}
F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
{
update();
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
return F64Seconds((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
return F64Seconds((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0) / (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
}
S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
{
return mBuffers->mStackTimers[stat.getIndex()].mCalls;
update();
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
return accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0);
}
F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
{
update();
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
return F64Seconds((F64)(accumulator.mTotalTimeCounter)
return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
/ ((F64)LLTrace::BlockTimerStatHandle::countsPerSecond() * mElapsedSeconds.value()));
}
F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
{
update();
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
return F64Seconds((F64)(accumulator.mSelfTimeCounter)
return F64Seconds((F64)(accumulator.mSelfTimeCounter + (active_accumulator ? active_accumulator->mSelfTimeCounter : 0))
/ ((F64)LLTrace::BlockTimerStatHandle::countsPerSecond() * mElapsedSeconds.value()));
}
F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
{
return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value();
update();
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value();
}
bool Recording::hasValue(const StatType<MemAccumulator>& stat)
{
return mBuffers->mMemStats[stat.getIndex()].mSize.hasValue();
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mSize.hasValue() || (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.hasValue() : false);
}
F64Kilobytes Recording::getMin(const StatType<MemAccumulator>& stat)
{
return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(llmin(accumulator.mSize.getMin(), (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMin() : F32_MAX)));
}
F64Kilobytes Recording::getMean(const StatType<MemAccumulator>& stat)
{
return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->mSize.hasValue())
{
return F64Bytes(lerp(accumulator.mSize.getMean(), active_accumulator->mSize.getMean(), active_accumulator->mSize.getSampleCount() / (accumulator.mSize.getSampleCount() + active_accumulator->mSize.getSampleCount())));
}
else
{
return F64Bytes(accumulator.mSize.getMean());
}
}
F64Kilobytes Recording::getMax(const StatType<MemAccumulator>& stat)
{
return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(llmax(accumulator.mSize.getMax(), active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMax() : F32_MIN));
}
F64Kilobytes Recording::getStandardDeviation(const StatType<MemAccumulator>& stat)
{
return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue())
{
F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator.mSize, active_accumulator->mSize);
return F64Bytes(sqrtf(sum_of_squares / (accumulator.mSize.getSamplingTime().value() + active_accumulator->mSize.getSamplingTime().value())));
}
else
{
return F64Bytes(accumulator.mSize.getStandardDeviation());
}
}
F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat)
{
return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(active_accumulator ? active_accumulator->mSize.getLastValue() : accumulator.mSize.getLastValue());
}
bool Recording::hasValue(const StatType<MemAccumulator::AllocationFacet>& stat)
{
return mBuffers->mMemStats[stat.getIndex()].mAllocations.hasValue();
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mAllocations.hasValue() || (active_accumulator ? active_accumulator->mAllocations.hasValue() : false);
}
F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat)
{
return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum());
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0));
}
F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat)
{
return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum() / mElapsedSeconds.value());
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes((accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0)) / mElapsedSeconds.value());
}
S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat)
{
return mBuffers->mMemStats[stat.getIndex()].mAllocations.getSampleCount();
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mAllocations.getSampleCount() + (active_accumulator ? active_accumulator->mAllocations.getSampleCount() : 0);
}
bool Recording::hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat)
{
return mBuffers->mMemStats[stat.getIndex()].mDeallocations.hasValue();
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mDeallocations.hasValue() || (active_accumulator ? active_accumulator->mDeallocations.hasValue() : false);
}
F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat)
{
return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum());
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0));
}
F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat)
{
return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum() / mElapsedSeconds.value());
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes((accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0)) / mElapsedSeconds.value());
}
S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat)
{
return mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSampleCount();
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mDeallocations.getSampleCount() + (active_accumulator ? active_accumulator->mDeallocations.getSampleCount() : 0);
}
bool Recording::hasValue(const StatType<CountAccumulator>& stat)
{
return mBuffers->mCounts[stat.getIndex()].hasValue();
update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
return accumulator.hasValue() || (active_accumulator ? active_accumulator->hasValue() : false);
}
F64 Recording::getSum(const StatType<CountAccumulator>& stat)
{
return mBuffers->mCounts[stat.getIndex()].getSum();
}
F64 Recording::getSum( const StatType<EventAccumulator>& stat)
{
return (F64)mBuffers->mEvents[stat.getIndex()].getSum();
update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
return accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
}
F64 Recording::getPerSec( const StatType<CountAccumulator>& stat )
{
F64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
return sum / mElapsedSeconds.value();
update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
F64 sum = accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
return sum / mElapsedSeconds.value();
}
S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat )
{
return mBuffers->mCounts[stat.getIndex()].getSampleCount();
update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
}
bool Recording::hasValue(const StatType<SampleAccumulator>& stat)
{
return mBuffers->mSamples[stat.getIndex()].hasValue();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
}
F64 Recording::getMin( const StatType<SampleAccumulator>& stat )
{
return mBuffers->mSamples[stat.getIndex()].getMin();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
}
F64 Recording::getMax( const StatType<SampleAccumulator>& stat )
{
return mBuffers->mSamples[stat.getIndex()].getMax();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
}
F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
{
return mBuffers->mSamples[stat.getIndex()].getMean();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue())
{
return lerp(accumulator.getMean(), active_accumulator->getMean(), active_accumulator->getSampleCount() / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
}
else
{
return accumulator.getMean();
}
}
F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
{
return mBuffers->mSamples[stat.getIndex()].getStandardDeviation();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue())
{
F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
return sqrtf(sum_of_squares / (accumulator.getSamplingTime() + active_accumulator->getSamplingTime()));
}
else
{
return accumulator.getStandardDeviation();
}
}
F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat )
{
return mBuffers->mSamples[stat.getIndex()].getLastValue();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getLastValue() : accumulator.getLastValue());
}
S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat )
{
return mBuffers->mSamples[stat.getIndex()].getSampleCount();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return accumulator.getSampleCount() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSampleCount() : 0);
}
bool Recording::hasValue(const StatType<EventAccumulator>& stat)
{
return mBuffers->mEvents[stat.getIndex()].hasValue();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
}
F64 Recording::getSum( const StatType<EventAccumulator>& stat)
{
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return (F64)(accumulator.getSum() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSum() : 0));
}
F64 Recording::getMin( const StatType<EventAccumulator>& stat )
{
return mBuffers->mEvents[stat.getIndex()].getMin();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
}
F64 Recording::getMax( const StatType<EventAccumulator>& stat )
{
return mBuffers->mEvents[stat.getIndex()].getMax();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
}
F64 Recording::getMean( const StatType<EventAccumulator>& stat )
{
return mBuffers->mEvents[stat.getIndex()].getMean();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue())
{
return lerp(accumulator.getMean(), active_accumulator->getMean(), active_accumulator->getSampleCount() / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
}
else
{
return accumulator.getMean();
}
}
F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
{
return mBuffers->mEvents[stat.getIndex()].getStandardDeviation();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue())
{
F64 sum_of_squares = EventAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
return sqrtf(sum_of_squares / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
}
else
{
return accumulator.getStandardDeviation();
}
}
F64 Recording::getLastValue( const StatType<EventAccumulator>& stat )
{
return mBuffers->mEvents[stat.getIndex()].getLastValue();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return active_accumulator ? active_accumulator->getLastValue() : accumulator.getLastValue();
}
S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
{
return mBuffers->mEvents[stat.getIndex()].getSampleCount();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
}
///////////////////////////////////////////////////////////////////////

View File

@ -322,7 +322,7 @@ namespace LLTrace
LLTimer mSamplingTimer;
F64Seconds mElapsedSeconds;
LLCopyOnWritePointer<AccumulatorBufferGroup> mBuffers;
bool mInHandOff;
AccumulatorBufferGroup* mActiveBuffers;
};

View File

@ -131,7 +131,7 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
}
void ThreadRecorder::activate( AccumulatorBufferGroup* recording, bool from_handoff )
AccumulatorBufferGroup* ThreadRecorder::activate( AccumulatorBufferGroup* recording)
{
ActiveRecording* active_recording = new ActiveRecording(recording);
if (!mActiveRecordings.empty())
@ -144,6 +144,7 @@ void ThreadRecorder::activate( AccumulatorBufferGroup* recording, bool from_hand
mActiveRecordings.push_back(active_recording);
mActiveRecordings.back()->mPartialRecording.makeCurrent();
return &active_recording->mPartialRecording;
}
ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )

View File

@ -47,7 +47,7 @@ namespace LLTrace
~ThreadRecorder();
void activate(AccumulatorBufferGroup* recording, bool from_handoff = false);
AccumulatorBufferGroup* activate(AccumulatorBufferGroup* recording);
void deactivate(AccumulatorBufferGroup* recording);
active_recording_list_t::iterator bringUpToDate(AccumulatorBufferGroup* recording);

View File

@ -109,8 +109,9 @@ namespace tut
at_work.stop();
drink_coffee(1, S32VentiCup(1));
}
after_3pm.stop();
all_day.stop();
// don't need to stop recordings to get accurate values out of them
//after_3pm.stop();
//all_day.stop();
ensure("count stats are counted when recording is active",
at_work.getSum(sCupsOfCoffeeConsumed) == 3