SH-3275 WIP Update viewer metrics system to be more flexible

cleaned up accumulator merging logic
introduced frame recording to LLTrace directly instead of going through LLViewerStats
moved consumer code over to frame recording instead of whatever the current active recording was
master
Richard Linden 2012-10-12 00:20:19 -07:00
parent b3107e3764
commit 0f58ca02cd
11 changed files with 357 additions and 305 deletions

View File

@ -101,16 +101,6 @@ namespace LLTrace
}
}
void addDeltas(const AccumulatorBuffer<ACCUMULATOR>& start, const AccumulatorBuffer<ACCUMULATOR>& finish)
{
llassert(mNextStorageSlot == start.mNextStorageSlot && mNextStorageSlot == finish.mNextStorageSlot);
for (size_t i = 0; i < mNextStorageSlot; i++)
{
mStorage[i].addDeltas(start.mStorage[i], finish.mStorage[i]);
}
}
void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
{
for (size_t i = 0; i < mNextStorageSlot; i++)
@ -203,11 +193,12 @@ namespace LLTrace
public:
MeasurementAccumulator()
: mSum(0),
mMin(0),
mMax(0),
mMin(std::numeric_limits<T>::max()),
mMax(std::numeric_limits<T>::min()),
mMean(0),
mVarianceSum(0),
mNumSamples(0)
mNumSamples(0),
mLastValue(0)
{}
LL_FORCE_INLINE void sample(T value)
@ -251,20 +242,27 @@ namespace LLTrace
sd_2 = other.getStandardDeviation();
// 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
mVarianceSum = (F32)mNumSamples
if (n_1 == 0)
{
mVarianceSum = other.mVarianceSum;
}
else if (n_2 == 0)
{
// don't touch variance
// mVarianceSum = mVarianceSum;
}
else
{
mVarianceSum = (F32)mNumSamples
* ((((n_1 - 1.f) * sd_1 * sd_1)
+ ((n_2 - 1.f) * sd_2 * sd_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));
}
mLastValue = other.mLastValue;
}
void addDeltas(const MeasurementAccumulator<T>& start, const MeasurementAccumulator<T>& finish)
{
llerrs << "Delta merge invalid for measurement accumulators" << llendl;
}
void reset()
{
mNumSamples = 0;
@ -313,12 +311,6 @@ namespace LLTrace
mNumSamples += other.mNumSamples;
}
void addDeltas(const RateAccumulator<T>& start, const RateAccumulator<T>& finish)
{
mSum += finish.mSum - start.mSum;
mNumSamples += finish.mNumSamples - start.mNumSamples;
}
void reset()
{
mNumSamples = 0;
@ -464,13 +456,6 @@ namespace LLTrace
mCalls += other.mCalls;
}
void addDeltas(const TimerAccumulator& start, const TimerAccumulator& finish)
{
mTotalTimeCounter += finish.mTotalTimeCounter - start.mTotalTimeCounter;
mChildTimeCounter += finish.mChildTimeCounter - start.mChildTimeCounter;
mCalls += finish.mCalls - start.mCalls;
}
void reset()
{
mTotalTimeCounter = 0;

View File

@ -68,16 +68,16 @@ void Recording::handleReset()
}
void Recording::handleStart()
{
mSamplingTimer.reset();
LLTrace::get_thread_recorder()->activate(this);
{
mSamplingTimer.reset();
LLTrace::get_thread_recorder()->activate(this);
}
void Recording::handleStop()
{
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
LLTrace::get_thread_recorder()->deactivate(this);
}
{
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
LLTrace::get_thread_recorder()->deactivate(this);
}
void Recording::handleSplitTo(Recording& other)
{
@ -105,10 +105,204 @@ void Recording::mergeRecording( const Recording& other )
mStackTimers.write()->addSamples(*other.mStackTimers);
}
void Recording::mergeRecordingDelta(const Recording& baseline, const Recording& target)
///////////////////////////////////////////////////////////////////////
// Recording
///////////////////////////////////////////////////////////////////////
PeriodicRecording::PeriodicRecording( S32 num_periods )
: mNumPeriods(num_periods),
mCurPeriod(0),
mTotalValid(false),
mRecordingPeriods( new Recording[num_periods])
{
mRates.write()->addDeltas(*baseline.mRates, *target.mRates);
mStackTimers.write()->addDeltas(*baseline.mStackTimers, *target.mStackTimers);
llassert(mNumPeriods > 0);
}
PeriodicRecording::~PeriodicRecording()
{
delete[] mRecordingPeriods;
}
void PeriodicRecording::nextPeriod()
{
EPlayState play_state = getPlayState();
getCurRecordingPeriod().stop();
mCurPeriod = (mCurPeriod + 1) % mNumPeriods;
switch(play_state)
{
case STOPPED:
break;
case PAUSED:
getCurRecordingPeriod().pause();
break;
case STARTED:
getCurRecordingPeriod().start();
break;
}
// new period, need to recalculate total
mTotalValid = false;
}
Recording& PeriodicRecording::getTotalRecording()
{
if (!mTotalValid)
{
mTotalRecording.reset();
for (S32 i = (mCurPeriod + 1) % mNumPeriods; i < mCurPeriod; i++)
{
mTotalRecording.mergeRecording(mRecordingPeriods[i]);
}
}
mTotalValid = true;
return mTotalRecording;
}
void PeriodicRecording::handleStart()
{
getCurRecordingPeriod().handleStart();
}
void PeriodicRecording::handleStop()
{
getCurRecordingPeriod().handleStop();
}
void PeriodicRecording::handleReset()
{
getCurRecordingPeriod().handleReset();
}
void PeriodicRecording::handleSplitTo( PeriodicRecording& other )
{
getCurRecordingPeriod().handleSplitTo(other.getCurRecordingPeriod());
}
///////////////////////////////////////////////////////////////////////
// ExtendableRecording
///////////////////////////////////////////////////////////////////////
void ExtendableRecording::extend()
{
mAcceptedRecording.mergeRecording(mPotentialRecording);
mPotentialRecording.reset();
}
void ExtendableRecording::handleStart()
{
mPotentialRecording.handleStart();
}
void ExtendableRecording::handleStop()
{
mPotentialRecording.handleStop();
}
void ExtendableRecording::handleReset()
{
mAcceptedRecording.handleReset();
mPotentialRecording.handleReset();
}
void ExtendableRecording::handleSplitTo( ExtendableRecording& other )
{
mPotentialRecording.handleSplitTo(other.mPotentialRecording);
}
PeriodicRecording& get_frame_recording()
{
static PeriodicRecording sRecording(64);
sRecording.start();
return sRecording;
}
}
void LLVCRControlsMixinCommon::start()
{
switch (mPlayState)
{
case STOPPED:
handleReset();
handleStart();
break;
case PAUSED:
handleStart();
break;
case STARTED:
handleReset();
break;
}
mPlayState = STARTED;
}
void LLVCRControlsMixinCommon::stop()
{
switch (mPlayState)
{
case STOPPED:
break;
case PAUSED:
handleStop();
break;
case STARTED:
handleStop();
break;
}
mPlayState = STOPPED;
}
void LLVCRControlsMixinCommon::pause()
{
switch (mPlayState)
{
case STOPPED:
break;
case PAUSED:
break;
case STARTED:
handleStop();
break;
}
mPlayState = PAUSED;
}
void LLVCRControlsMixinCommon::resume()
{
switch (mPlayState)
{
case STOPPED:
handleStart();
break;
case PAUSED:
handleStart();
break;
case STARTED:
break;
}
mPlayState = STARTED;
}
void LLVCRControlsMixinCommon::restart()
{
switch (mPlayState)
{
case STOPPED:
handleReset();
handleStart();
break;
case PAUSED:
handleReset();
handleStart();
break;
case STARTED:
handleReset();
break;
}
mPlayState = STARTED;
}
void LLVCRControlsMixinCommon::reset()
{
handleReset();
}

View File

@ -34,27 +34,11 @@
#include "lltimer.h"
#include "lltrace.h"
template<typename DERIVED>
class LL_COMMON_API LLVCRControlsMixinInterface
class LL_COMMON_API LLVCRControlsMixinCommon
{
public:
virtual ~LLVCRControlsMixinInterface() {}
// trigger data accumulation (without reset)
virtual void handleStart() = 0;
// stop data accumulation, should put object in queryable state
virtual void handleStop() = 0;
// clear accumulated values, can be called while started
virtual void handleReset() = 0;
// atomically stop this object while starting the other
// no data can be missed in between stop and start
virtual void handleSplitTo(DERIVED& other) = 0;
};
virtual ~LLVCRControlsMixinCommon() {}
template<typename DERIVED>
class LL_COMMON_API LLVCRControlsMixin
: private LLVCRControlsMixinInterface<DERIVED>
{
public:
enum EPlayState
{
STOPPED,
@ -62,94 +46,39 @@ public:
STARTED
};
void start()
{
switch (mPlayState)
{
case STOPPED:
handleReset();
handleStart();
break;
case PAUSED:
handleStart();
break;
case STARTED:
handleReset();
break;
}
mPlayState = STARTED;
}
void start();
void stop();
void pause();
void resume();
void restart();
void reset();
void stop()
{
switch (mPlayState)
{
case STOPPED:
break;
case PAUSED:
handleStop();
break;
case STARTED:
break;
}
mPlayState = STOPPED;
}
bool isStarted() { return mPlayState == STARTED; }
bool isPaused() { return mPlayState == PAUSED; }
bool isStopped() { return mPlayState == STOPPED; }
EPlayState getPlayState() { return mPlayState; }
void pause()
{
switch (mPlayState)
{
case STOPPED:
break;
case PAUSED:
break;
case STARTED:
handleStop();
break;
}
mPlayState = PAUSED;
}
protected:
LLVCRControlsMixinCommon()
: mPlayState(STOPPED)
{}
void resume()
{
switch (mPlayState)
{
case STOPPED:
handleStart();
break;
case PAUSED:
handleStart();
break;
case STARTED:
break;
}
mPlayState = STARTED;
}
private:
// trigger data accumulation (without reset)
virtual void handleStart() = 0;
// stop data accumulation, should put object in queryable state
virtual void handleStop() = 0;
// clear accumulated values, can be called while started
virtual void handleReset() = 0;
void restart()
{
switch (mPlayState)
{
case STOPPED:
handleReset();
handleStart();
break;
case PAUSED:
handleReset();
handleStart();
break;
case STARTED:
handleReset();
break;
}
mPlayState = STARTED;
}
void reset()
{
handleReset();
}
EPlayState mPlayState;
};
template<typename DERIVED>
class LLVCRControlsMixin
: public LLVCRControlsMixinCommon
{
public:
void splitTo(DERIVED& other)
{
onSplitTo(other);
@ -159,32 +88,15 @@ public:
{
other.onSplitTo(*this);
}
bool isStarted() { return mPlayState == STARTED; }
bool isPaused() { return mPlayState == PAUSED; }
bool isStopped() { return mPlayState == STOPPED; }
EPlayState getPlayState() { return mPlayState; }
protected:
LLVCRControlsMixin()
: mPlayState(STOPPED)
{}
private:
EPlayState mPlayState;
// atomically stop this object while starting the other
// no data can be missed in between stop and start
virtual void handleSplitTo(DERIVED& other) = 0;
};
namespace LLTrace
{
//template<typename T, typename IS_UNIT> class Rate;
//template<typename T, typename IS_UNIT> class Measurement;
//template<typename T> class Count;
//template<typename T> class AccumulatorBuffer;
//template<typename T> class RateAccumulator;
//template<typename T> class MeasurementAccumulator;
//class TimerAccumulator;
class LL_COMMON_API Recording : public LLVCRControlsMixin<Recording>
{
public:
@ -196,7 +108,6 @@ namespace LLTrace
bool isPrimary() const;
void mergeRecording(const Recording& other);
void mergeRecordingDelta(const Recording& baseline, const Recording& target);
void update();
@ -308,15 +219,13 @@ namespace LLTrace
F64 getSampleTime() const { return mElapsedSeconds; }
private:
friend class PeriodicRecording;
// implementation for LLVCRControlsMixin
/*virtual*/ void handleStart();
/*virtual*/ void handleStop();
/*virtual*/ void handleReset();
/*virtual*/ void handleSplitTo(Recording& other);
private:
friend class ThreadRecorder;
// returns data for current thread
class ThreadRecorder* getThreadRecorder();
@ -333,38 +242,19 @@ namespace LLTrace
: public LLVCRControlsMixin<PeriodicRecording>
{
public:
PeriodicRecording(S32 num_periods)
: mNumPeriods(num_periods),
mCurPeriod(0),
mTotalValid(false),
mRecordingPeriods(new Recording[num_periods])
{
llassert(mNumPeriods > 0);
PeriodicRecording(S32 num_periods);
~PeriodicRecording();
void nextPeriod();
Recording& getLastRecordingPeriod()
{
return mRecordingPeriods[(mCurPeriod + mNumPeriods - 1) % mNumPeriods];
}
~PeriodicRecording()
const Recording& getLastRecordingPeriod() const
{
delete[] mRecordingPeriods;
}
void nextPeriod()
{
EPlayState play_state = getPlayState();
getCurRecordingPeriod().stop();
mCurPeriod = (mCurPeriod + 1) % mNumPeriods;
switch(play_state)
{
case STOPPED:
break;
case PAUSED:
getCurRecordingPeriod().pause();
break;
case STARTED:
getCurRecordingPeriod().start();
break;
}
// new period, need to recalculate total
mTotalValid = false;
return mRecordingPeriods[(mCurPeriod + mNumPeriods - 1) % mNumPeriods];
}
Recording& getCurRecordingPeriod()
@ -377,41 +267,16 @@ namespace LLTrace
return mRecordingPeriods[mCurPeriod];
}
Recording& getTotalRecording()
{
if (!mTotalValid)
{
mTotalRecording.reset();
for (S32 i = (mCurPeriod + 1) % mNumPeriods; i < mCurPeriod; i++)
{
mTotalRecording.mergeRecording(mRecordingPeriods[i]);
}
}
mTotalValid = true;
return mTotalRecording;
}
Recording& getTotalRecording();
private:
// implementation for LLVCRControlsMixin
/*virtual*/ void handleStart()
{
getCurRecordingPeriod().handleStart();
}
/*virtual*/ void handleStart();
/*virtual*/ void handleStop();
/*virtual*/ void handleReset();
/*virtual*/ void handleStop()
{
getCurRecordingPeriod().handleStop();
}
/*virtual*/ void handleReset()
{
getCurRecordingPeriod().handleReset();
}
/*virtual*/ void handleSplitTo(PeriodicRecording& other)
{
getCurRecordingPeriod().handleSplitTo(other.getCurRecordingPeriod());
}
/*virtual*/ void handleSplitTo(PeriodicRecording& other);
Recording* mRecordingPeriods;
Recording mTotalRecording;
@ -419,6 +284,24 @@ namespace LLTrace
S32 mNumPeriods,
mCurPeriod;
};
PeriodicRecording& get_frame_recording();
class ExtendableRecording
: public LLVCRControlsMixin<ExtendableRecording>
{
void extend();
private:
// implementation for LLVCRControlsMixin
/*virtual*/ void handleStart();
/*virtual*/ void handleStop();
/*virtual*/ void handleReset();
/*virtual*/ void handleSplitTo(ExtendableRecording& other);
Recording mAcceptedRecording;
Recording mPotentialRecording;
};
}
#endif // LL_LLTRACERECORDING_H

View File

@ -36,15 +36,13 @@ namespace LLTrace
///////////////////////////////////////////////////////////////////////
ThreadRecorder::ThreadRecorder()
: mPrimaryRecording(NULL)
{
get_thread_recorder() = this;
mFullRecording.start();
}
ThreadRecorder::ThreadRecorder( const ThreadRecorder& other )
: mFullRecording(other.mFullRecording),
mPrimaryRecording(NULL)
: mFullRecording(other.mFullRecording)
{
get_thread_recorder() = this;
mFullRecording.start();
@ -55,45 +53,40 @@ ThreadRecorder::~ThreadRecorder()
get_thread_recorder() = NULL;
}
//TODO: remove this and use llviewerstats recording
Recording* ThreadRecorder::getPrimaryRecording()
{
return mPrimaryRecording;
}
void ThreadRecorder::activate( Recording* recording )
{
mActiveRecordings.push_front(ActiveRecording(mPrimaryRecording, recording));
mActiveRecordings.push_front(ActiveRecording(recording));
mActiveRecordings.front().mBaseline.makePrimary();
mPrimaryRecording = &mActiveRecordings.front().mBaseline;
}
std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Recording* recording )
{
for (std::list<ActiveRecording>::iterator it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
std::list<ActiveRecording>::iterator it, end_it;
for (it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
it != end_it;
++it)
{
std::list<ActiveRecording>::iterator next_it = it;
if (++next_it != mActiveRecordings.end())
++next_it;
// if we have another recording further down in the stack...
if (next_it != mActiveRecordings.end())
{
next_it->mergeMeasurements((*it));
// ...push our gathered data down to it
next_it->mBaseline.mergeRecording(it->mBaseline);
}
it->flushAccumulators(mPrimaryRecording);
// copy accumulated measurements into result buffer and clear accumulator (mBaseline)
it->moveBaselineToTarget();
if (it->mTargetRecording == recording)
{
if (next_it != mActiveRecordings.end())
{
next_it->mBaseline.makePrimary();
mPrimaryRecording = &next_it->mBaseline;
}
return it;
// found the recording, so return it
break;
}
}
return mActiveRecordings.end();
return it;
}
void ThreadRecorder::deactivate( Recording* recording )
@ -101,38 +94,34 @@ void ThreadRecorder::deactivate( Recording* recording )
std::list<ActiveRecording>::iterator it = update(recording);
if (it != mActiveRecordings.end())
{
// and if we've found the recording we wanted to update
std::list<ActiveRecording>::iterator next_it = it;
++next_it;
if (next_it != mActiveRecordings.end())
{
next_it->mTargetRecording->makePrimary();
}
mActiveRecordings.erase(it);
}
}
ThreadRecorder::ActiveRecording::ActiveRecording( Recording* source, Recording* target )
ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target )
: mTargetRecording(target)
{
// take snapshots of current values rates and timers
if (source)
{
mBaseline.mRates.write()->copyFrom(*source->mRates);
mBaseline.mStackTimers.write()->copyFrom(*source->mStackTimers);
}
}
void ThreadRecorder::ActiveRecording::mergeMeasurements(ThreadRecorder::ActiveRecording& other)
void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
{
mBaseline.mMeasurements.write()->addSamples(*other.mBaseline.mMeasurements);
}
void ThreadRecorder::ActiveRecording::flushAccumulators(Recording* current)
{
// accumulate statistics-like measurements
mTargetRecording->mMeasurements.write()->addSamples(*mBaseline.mMeasurements);
// for rate-like measurements, merge total change since baseline
mTargetRecording->mRates.write()->addDeltas(*mBaseline.mRates, *current->mRates);
mTargetRecording->mStackTimers.write()->addDeltas(*mBaseline.mStackTimers, *current->mStackTimers);
// reset baselines
mBaseline.mRates.write()->copyFrom(*current->mRates);
mBaseline.mStackTimers.write()->copyFrom(*current->mStackTimers);
mTargetRecording->mRates.write()->addSamples(*mBaseline.mRates);
mTargetRecording->mStackTimers.write()->addSamples(*mBaseline.mStackTimers);
mBaseline.mMeasurements.write()->reset();
mBaseline.mRates.write()->reset();
mBaseline.mStackTimers.write()->reset();
}
///////////////////////////////////////////////////////////////////////
// SlaveThreadRecorder
///////////////////////////////////////////////////////////////////////

View File

@ -51,19 +51,16 @@ namespace LLTrace
virtual void pushToMaster() = 0;
Recording* getPrimaryRecording();
protected:
struct ActiveRecording
{
ActiveRecording(Recording* source, Recording* target);
ActiveRecording(Recording* target);
Recording* mTargetRecording;
Recording mBaseline;
void mergeMeasurements(ActiveRecording& other);
void flushAccumulators(Recording* current);
void moveBaselineToTarget();
};
Recording* mPrimaryRecording;
Recording mFullRecording;
std::list<ActiveRecording> mActiveRecordings;
};

View File

@ -37,7 +37,6 @@
#include "llstat.h"
#include "lluictrlfactory.h"
#include "lltracerecording.h"
#include "lltracethreadrecorder.h"
///////////////////////////////////////////////////////////////////////////////////
@ -112,17 +111,17 @@ void LLStatBar::draw()
}
else if (mFloatStatp)
{
LLTrace::Recording* recording = LLTrace::get_thread_recorder()->getPrimaryRecording();
LLTrace::Recording& recording = LLTrace::get_frame_recording().getLastRecordingPeriod();
if (mPerSec)
{
current = recording->getSum(*mFloatStatp) / recording->getSampleTime();
current = recording.getPerSec(*mFloatStatp);
//min = recording->getMin(*mFloatStatp) / recording->getSampleTime();
//max = recording->getMax(*mFloatStatp) / recording->getSampleTime();
//mean = recording->getMean(*mFloatStatp) / recording->getSampleTime();
}
else
{
current = recording->getSum(*mFloatStatp);
current = recording.getSum(*mFloatStatp);
//min = recording->getMin(*mFloatStatp);
//max = recording->getMax(*mFloatStatp);
//mean = recording->getMean(*mFloatStatp);

View File

@ -29,8 +29,7 @@
#include "llview.h"
#include "llframetimer.h"
#include "lltrace.h"
#include "lltracerecording.h"
class LLStat;
class LLStatBar : public LLView
@ -39,19 +38,24 @@ public:
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
Optional<std::string> label;
Optional<std::string> unit_label;
Optional<F32> bar_min;
Optional<F32> bar_max;
Optional<F32> tick_spacing;
Optional<F32> label_spacing;
Optional<U32> precision;
Optional<F32> update_rate;
Optional<bool> show_per_sec;
Optional<bool> show_bar;
Optional<bool> show_history;
Optional<bool> show_mean;
Optional<std::string> stat;
Optional<std::string> label,
unit_label;
Optional<F32> bar_min,
bar_max,
tick_spacing,
label_spacing,
update_rate;
Optional<U32> precision;
Optional<bool> show_per_sec,
show_bar,
show_history,
show_mean;
Optional<std::string> stat;
Params()
: label("label"),
unit_label("unit_label"),
@ -92,6 +96,7 @@ private:
BOOL mDisplayBar; // Display the bar graph.
BOOL mDisplayHistory;
BOOL mDisplayMean; // If true, display mean, if false, display current value
LLTrace::PeriodicRecording* mFrameRecording;
LLStat* mStatp;
LLTrace::Rate<F32>* mFloatStatp;

View File

@ -86,15 +86,15 @@ void LLStatGraph::draw()
}
else if (mF32Statp)
{
LLTrace::Recording* recording = LLTrace::get_thread_recorder()->getPrimaryRecording();
LLTrace::Recording& recording = LLTrace::get_frame_recording().getLastRecordingPeriod();
if (mPerSec)
{
mValue = recording->getSum(*mF32Statp) / recording->getSampleTime();
mValue = recording.getPerSec(*mF32Statp);
}
else
{
mValue = recording->getSum(*mF32Statp);
mValue = recording.getSum(*mF32Statp);
}
}

View File

@ -497,6 +497,8 @@ void update_statistics()
texture_stats_timer.reset();
}
}
LLTrace::get_frame_recording().nextPeriod();
}
class ViewerStatsResponder : public LLHTTPClient::Responder

View File

@ -412,14 +412,12 @@ public:
};
LLTrace::Recording& getRecording() { return mRecording; }
LLTrace::Recording& getFrameRecording() { return mFrameRecording; }
private:
F64 mStats[ST_COUNT];
LLTrace::Recording mRecording;
LLTrace::Recording mFrameRecording;
F64 mStats[ST_COUNT];
LLTrace::Recording mRecording;
F64 mLastTimeDiff; // used for time stat updates
F64 mLastTimeDiff; // used for time stat updates
};
static const F32 SEND_STATS_PERIOD = 300.0f;

View File

@ -58,7 +58,7 @@
#include "pipeline.h"
#include "llappviewer.h"
#include "llxuiparser.h"
#include "lltracethreadrecorder.h"
#include "lltracerecording.h"
#include "llviewerdisplay.h"
////////////////////////////////////////////////////////////////////////////
@ -621,9 +621,9 @@ void LLViewerTextureList::updateImages(F32 max_time)
}
cleared = FALSE;
LLTrace::Recording* recording = LLTrace::get_thread_recorder()->getPrimaryRecording();
LLTrace::Recording& recording = LLTrace::get_frame_recording().getTotalRecording();
LLAppViewer::getTextureFetch()->setTextureBandwidth(recording->getPerSec(LLStatViewer::TEXTURE_KBIT).value());
LLAppViewer::getTextureFetch()->setTextureBandwidth(recording.getPerSec(LLStatViewer::TEXTURE_KBIT).value());
LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages);
LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount);