summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/lltrace.h12
-rw-r--r--indra/llcommon/lltracerecording.cpp43
-rw-r--r--indra/llcommon/lltracerecording.h249
-rw-r--r--indra/llcommon/lltracethreadrecorder.cpp4
-rw-r--r--indra/llcommon/llunit.h66
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 -; \