summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorRichard Linden <none@none>2012-10-09 18:02:47 -0700
committerRichard Linden <none@none>2012-10-09 18:02:47 -0700
commitaff9654c1115b4a74fc3ee8f9ca2c2ffa07f8d73 (patch)
tree4cbd07cad7b3d912324aee7513fb5462bab9d13b /indra/llcommon
parent3960fdf9e01619ddfd7903bcdd8d894f432752d0 (diff)
SH-3275 WIP Update viewer metrics system to be more flexible
added PeriodicRecorder class for frame by frame stats accumulation
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/lltrace.h4
-rw-r--r--indra/llcommon/lltracerecording.cpp35
-rw-r--r--indra/llcommon/lltracerecording.h247
-rw-r--r--indra/llcommon/llunit.h12
4 files changed, 261 insertions, 37 deletions
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d83ea77363..e655a3582e 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -353,7 +353,7 @@ namespace LLTrace
template<typename UNIT_T>
void sample(UNIT_T value)
{
- base_measurement_t::sample(value.get());
+ base_measurement_t::sample(value.value());
}
};
@@ -386,7 +386,7 @@ namespace LLTrace
template<typename UNIT_T>
void add(UNIT_T value)
{
- getPrimaryAccumulator().add(value.get());
+ getPrimaryAccumulator().add(value.value());
}
};
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index e4cff551f9..7cd6280f03 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -38,7 +38,6 @@ namespace LLTrace
Recording::Recording()
: mElapsedSeconds(0),
- mIsStarted(false),
mRates(new AccumulatorBuffer<RateAccumulator<F32> >()),
mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F32> >()),
mStackTimers(new AccumulatorBuffer<TimerAccumulator>())
@@ -47,13 +46,7 @@ Recording::Recording()
Recording::~Recording()
{}
-void Recording::start()
-{
- reset();
- resume();
-}
-
-void Recording::reset()
+void Recording::handleReset()
{
mRates.write()->reset();
mMeasurements.write()->reset();
@@ -63,24 +56,22 @@ void Recording::reset()
mSamplingTimer.reset();
}
-void Recording::resume()
+void Recording::handleStart()
+{
+ mSamplingTimer.reset();
+ LLTrace::get_thread_recorder()->activate(this);
+}
+
+void Recording::handleStop()
{
- if (!mIsStarted)
- {
- mSamplingTimer.reset();
- LLTrace::get_thread_recorder()->activate(this);
- mIsStarted = true;
- }
+ mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+ LLTrace::get_thread_recorder()->deactivate(this);
}
-void Recording::stop()
+void Recording::handleSplitTo(Recording& other)
{
- if (mIsStarted)
- {
- mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
- LLTrace::get_thread_recorder()->deactivate(this);
- mIsStarted = false;
- }
+ stop();
+ other.restart();
}
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index f9bc6b61b2..080007ba00 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -33,6 +33,147 @@
#include "llpointer.h"
#include "lltimer.h"
+template<typename DERIVED>
+class LL_COMMON_API LLVCRControlsMixinInterface
+{
+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;
+};
+
+template<typename DERIVED>
+class LL_COMMON_API LLVCRControlsMixin
+: private LLVCRControlsMixinInterface<DERIVED>
+{
+public:
+ enum EPlayState
+ {
+ STOPPED,
+ PAUSED,
+ STARTED
+ };
+
+ void start()
+ {
+ switch (mPlayState)
+ {
+ case STOPPED:
+ handleReset();
+ handleStart();
+ break;
+ case PAUSED:
+ handleStart();
+ break;
+ case STARTED:
+ handleReset();
+ break;
+ }
+ mPlayState = STARTED;
+ }
+
+ void stop()
+ {
+ switch (mPlayState)
+ {
+ case STOPPED:
+ break;
+ case PAUSED:
+ handleStop();
+ break;
+ case STARTED:
+ break;
+ }
+ mPlayState = STOPPED;
+ }
+
+ void pause()
+ {
+ switch (mPlayState)
+ {
+ case STOPPED:
+ break;
+ case PAUSED:
+ break;
+ case STARTED:
+ handleStop();
+ break;
+ }
+ mPlayState = PAUSED;
+ }
+
+ void resume()
+ {
+ switch (mPlayState)
+ {
+ case STOPPED:
+ handleStart();
+ break;
+ case PAUSED:
+ handleStart();
+ break;
+ case STARTED:
+ break;
+ }
+ mPlayState = STARTED;
+ }
+
+ void restart()
+ {
+ switch (mPlayState)
+ {
+ case STOPPED:
+ handleReset();
+ handleStart();
+ break;
+ case PAUSED:
+ handleReset();
+ handleStart();
+ break;
+ case STARTED:
+ handleReset();
+ break;
+ }
+ mPlayState = STARTED;
+ }
+
+ void reset()
+ {
+ handleReset();
+ }
+
+ void splitTo(DERIVED& other)
+ {
+ onSplitTo(other);
+ }
+
+ void splitFrom(DERIVED& other)
+ {
+ 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;
+};
+
namespace LLTrace
{
template<typename T, typename IS_UNIT> class Rate;
@@ -43,7 +184,7 @@ namespace LLTrace
template<typename T> class MeasurementAccumulator;
class TimerAccumulator;
- class LL_COMMON_API Recording
+ class LL_COMMON_API Recording : public LLVCRControlsMixin<Recording>
{
public:
Recording();
@@ -53,16 +194,9 @@ namespace LLTrace
void makePrimary();
bool isPrimary();
- void start();
- void stop();
- void resume();
-
void mergeSamples(const Recording& other);
void mergeDeltas(const Recording& baseline, const Recording& target);
- void reset();
-
- bool isStarted() { return mIsStarted; }
// Rate accessors
F32 getSum(const Rate<F32, void>& stat);
@@ -89,6 +223,14 @@ namespace LLTrace
F64 getSampleTime() { return mElapsedSeconds; }
private:
+ friend class PeriodicRecording;
+ // implementation for LLVCRControlsMixin
+ /*virtual*/ void handleStart();
+ /*virtual*/ void handleStop();
+ /*virtual*/ void handleReset();
+ /*virtual*/ void handleSplitTo(Recording& other);
+
+
friend class ThreadRecorder;
// returns data for current thread
class ThreadRecorder* getThreadRecorder();
@@ -97,14 +239,99 @@ namespace LLTrace
LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F32> > > mMeasurements;
LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> > mStackTimers;
- bool mIsStarted;
LLTimer mSamplingTimer;
F64 mElapsedSeconds;
};
- class LL_COMMON_API PeriodicRecording
+ class LL_COMMON_API PeriodicRecording
+ : public LLVCRControlsMixin<PeriodicRecording>
{
+ public:
+ PeriodicRecording(S32 num_periods)
+ : mNumPeriods(num_periods),
+ mCurPeriod(0),
+ mTotalValid(false),
+ mRecordingPeriods(new Recording[num_periods])
+ {
+ llassert(mNumPeriods > 0);
+ }
+
+ ~PeriodicRecording()
+ {
+ 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;
+ }
+
+ Recording& getCurRecordingPeriod()
+ {
+ return mRecordingPeriods[mCurPeriod];
+ }
+
+ const Recording& getCurRecordingPeriod() const
+ {
+ return mRecordingPeriods[mCurPeriod];
+ }
+
+ Recording& getTotalRecording()
+ {
+ if (!mTotalValid)
+ {
+ mTotalRecording.reset();
+ for (S32 i = (mCurPeriod + 1) % mNumPeriods; i < mCurPeriod; i++)
+ {
+ mTotalRecording.mergeSamples(mRecordingPeriods[i]);
+ }
+ }
+ mTotalValid = true;
+ return mTotalRecording;
+ }
+
+ private:
+ // implementation for LLVCRControlsMixin
+ /*virtual*/ void handleStart()
+ {
+ getCurRecordingPeriod().handleStart();
+ }
+
+ /*virtual*/ void handleStop()
+ {
+ getCurRecordingPeriod().handleStop();
+ }
+
+ /*virtual*/ void handleReset()
+ {
+ getCurRecordingPeriod().handleReset();
+ }
+
+ /*virtual*/ void handleSplitTo(PeriodicRecording& other)
+ {
+ getCurRecordingPeriod().handleSplitTo(other.getCurRecordingPeriod());
+ }
+ Recording* mRecordingPeriods;
+ Recording mTotalRecording;
+ bool mTotalValid;
+ S32 mNumPeriods,
+ mCurPeriod;
};
}
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 9d78df7cae..52b837fdc3 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -44,13 +44,19 @@ struct LLUnit : public BASE_UNIT
: BASE_UNIT(convertToBase(value))
{}
- operator value_t() { return get(); }
+ operator value_t() { return value(); }
- value_t get() const
+ value_t value() const
{
return convertToDerived(mValue);
}
+ template<typename CONVERTED_TYPE>
+ value_t value() const
+ {
+ return CONVERTED_TYPE(*this).value();
+ }
+
static value_t convertToBase(value_t derived_value)
{
return (value_t)((F32)derived_value * DERIVED_UNIT::conversionToBaseFactor());
@@ -84,7 +90,7 @@ struct LLUnit<T, T>
return *this;
}
- value_t get() { return mValue; }
+ value_t value() { return mValue; }
static value_t convertToBase(value_t derived_value)
{