diff options
-rw-r--r-- | indra/llcommon/lltrace.h | 4 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 25 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 246 | ||||
-rw-r--r-- | indra/llcommon/llunit.h | 12 |
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) { |