diff options
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/lltrace.h | 12 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 43 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 249 | ||||
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.cpp | 4 | ||||
-rw-r--r-- | indra/llcommon/llunit.h | 66 |
5 files changed, 300 insertions, 74 deletions
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index 539a37ce31..a6334e176b 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -253,10 +253,10 @@ namespace LLTrace // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm 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)); + + ((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; } @@ -369,7 +369,7 @@ namespace LLTrace template<typename UNIT_T> void sample(UNIT_T value) { - base_measurement_t::sample(value.get()); + base_measurement_t::sample(value.value()); } }; @@ -408,7 +408,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 e20bf797e7..0883930319 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -39,7 +39,6 @@ namespace LLTrace Recording::Recording() : mElapsedSeconds(0), - mIsStarted(false), mRates(new AccumulatorBuffer<RateAccumulator<F32> >()), mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F32> >()), mStackTimers(new AccumulatorBuffer<TimerAccumulator>()) @@ -48,13 +47,17 @@ Recording::Recording() Recording::~Recording() {} -void Recording::start() +void Recording::update() +{ + if (isStarted()) { - reset(); - resume(); + LLTrace::get_thread_recorder()->update(this); + mElapsedSeconds = 0.0; + mSamplingTimer.reset(); + } } -void Recording::reset() +void Recording::handleReset() { mRates.write()->reset(); mMeasurements.write()->reset(); @@ -64,34 +67,22 @@ void Recording::reset() mSamplingTimer.reset(); } -void Recording::update() -{ - if (mIsStarted) - { - LLTrace::get_thread_recorder()->update(this); - mElapsedSeconds = 0.0; - mSamplingTimer.reset(); - } -} - -void Recording::resume() -{ - if (!mIsStarted) +void Recording::handleStart() { 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(); } @@ -107,14 +98,14 @@ bool Recording::isPrimary() const return mRates->isPrimary(); } -void Recording::addSamples( const Recording& other ) +void Recording::mergeRecording( const Recording& other ) { mRates.write()->addSamples(*other.mRates); mMeasurements.write()->addSamples(*other.mMeasurements); mStackTimers.write()->addSamples(*other.mStackTimers); } -void Recording::addDeltas(const Recording& baseline, const Recording& target) +void Recording::mergeRecordingDelta(const Recording& baseline, const Recording& target) { mRates.write()->addDeltas(*baseline.mRates, *target.mRates); mStackTimers.write()->addDeltas(*baseline.mStackTimers, *target.mStackTimers); diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index d0c2e754f5..0a1a02fa02 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -34,6 +34,147 @@ #include "lltimer.h" #include "lltrace.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; @@ -44,7 +185,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(); @@ -54,15 +195,10 @@ namespace LLTrace void makePrimary(); bool isPrimary() const; - void start(); - void stop(); - void resume(); - void reset(); - void update(); - bool isStarted() const { return mIsStarted; } + void mergeRecording(const Recording& other); + void mergeRecordingDelta(const Recording& baseline, const Recording& target); - void addSamples(const Recording& other); - void addDeltas(const Recording& baseline, const Recording& target); + void update(); // Rate accessors template <typename T, typename IS_UNIT> @@ -173,6 +309,14 @@ 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); + + friend class ThreadRecorder; // returns data for current thread class ThreadRecorder* getThreadRecorder(); @@ -181,14 +325,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.mergeRecording(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/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 78833835c2..3acd06d553 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -161,13 +161,13 @@ void SlaveThreadRecorder::pushToMaster() void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source ) { LLMutexLock lock(&mRecorderMutex); - mRecorder.addSamples(source); + mRecorder.mergeRecording(source); } void SlaveThreadRecorder::SharedData::copyTo( Recording& sink ) { LLMutexLock lock(&mRecorderMutex); - sink.addSamples(mRecorder); + sink.mergeRecording(mRecorder); } /////////////////////////////////////////////////////////////////////// diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h index 4663070c42..2664bd77e9 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -49,11 +49,17 @@ struct LLUnitType : public BASE_UNIT return static_cast<unit_t&>(*this); } - 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 * unit_t::conversionToBaseFactor()); @@ -112,7 +118,7 @@ struct LLUnitType<STORAGE_TYPE, T, T> return static_cast<unit_t&>(*this); } - value_t get() { return mValue; } + value_t value() { return mValue; } static value_t convertToBase(value_t derived_value) { @@ -173,26 +179,26 @@ protected: value_t mValue; }; -#define LL_DECLARE_BASE_UNIT(unit_name) \ - template<typename STORAGE_TYPE> \ +#define LL_DECLARE_BASE_UNIT(unit_name) \ + template<typename STORAGE_TYPE> \ struct unit_name : public LLUnitType<STORAGE_TYPE, unit_name<STORAGE_TYPE> > \ - { \ + { \ typedef unit_name<STORAGE_TYPE> base_unit_t; \ typedef STORAGE_TYPE storage_t; \ \ - unit_name(STORAGE_TYPE value) \ + unit_name(STORAGE_TYPE value) \ : LLUnitType(value) \ - {} \ - \ - unit_name() \ - {} \ - \ + {} \ + \ + unit_name() \ + {} \ + \ template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE> \ unit_name(const LLUnitType<SOURCE_STORAGE_TYPE, unit_name, SOURCE_TYPE>& source) \ - { \ - setBaseValue(source.unit_t::get()); \ - } \ - \ + { \ + setBaseValue(source.unit_t::value()); \ + } \ + \ using LLUnitType::operator +; \ using LLUnitType::operator +=; \ using LLUnitType::operator -; \ @@ -203,28 +209,28 @@ protected: using LLUnitType::operator /=; \ }; -#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor) \ - template<typename STORAGE_TYPE> \ +#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor) \ + template<typename STORAGE_TYPE> \ struct derived_unit : public LLUnitType<STORAGE_TYPE, base_unit<STORAGE_TYPE>, derived_unit<STORAGE_TYPE> > \ - { \ + { \ typedef base_unit<STORAGE_TYPE> base_unit_t; \ typedef STORAGE_TYPE storage_t; \ \ - derived_unit(value_t value) \ + derived_unit(value_t value) \ : LLUnitType(value) \ - {} \ - \ - derived_unit() \ - {} \ - \ + {} \ + \ + derived_unit() \ + {} \ + \ template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE> \ derived_unit(const LLUnitType<SOURCE_STORAGE_TYPE, base_unit<STORAGE_TYPE>, SOURCE_TYPE>& source) \ - { \ - setBaseValue(source.base_unit_t::get()); \ - } \ - \ - static F32 conversionToBaseFactor() { return (F32)(conversion_factor); } \ - \ + { \ + setBaseValue(source.base_unit_t::value()); \ + } \ + \ + static F32 conversionToBaseFactor() { return (F32)(conversion_factor); } \ + \ using LLUnitType::operator +; \ using LLUnitType::operator +=; \ using LLUnitType::operator -; \ |