summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/lltrace.h4
-rw-r--r--indra/llcommon/lltracerecording.cpp25
-rw-r--r--indra/llcommon/lltracerecording.h246
-rw-r--r--indra/llcommon/llunit.h12
4 files changed, 256 insertions, 31 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 f0b17ef100..93d2136e7f 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();
@@ -73,24 +66,22 @@ void Recording::update()
}
}
-void Recording::resume()
+void Recording::handleStart()
{
- if (!mIsStarted)
- {
mSamplingTimer.reset();
LLTrace::get_thread_recorder()->activate(this);
- mIsStarted = true;
- }
}
-void Recording::stop()
-{
- if (mIsStarted)
+void Recording::handleStop()
{
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
LLTrace::get_thread_recorder()->deactivate(this);
- mIsStarted = false;
}
+
+void Recording::handleSplitTo(Recording& other)
+{
+ stop();
+ other.restart();
}
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 4d53cd9600..6e5f118cf6 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,18 +194,12 @@ 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();
void update();
-
- bool isStarted() { return mIsStarted; }
-
+
// Rate accessors
F32 getSum(const Rate<F32, void>& stat);
F32 getPerSec(const Rate<F32, void>& stat);
@@ -90,6 +225,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();
@@ -98,14 +241,99 @@ namespace LLTrace
LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F32> > > mMeasurements;
LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> > mStackTimers;
- bool mIsStarted;
LLTimer mSamplingTimer;
F64 mElapsedSeconds;
};
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)
{