summaryrefslogtreecommitdiff
path: root/indra/llcommon/lltrace.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/lltrace.h')
-rw-r--r--indra/llcommon/lltrace.h236
1 files changed, 207 insertions, 29 deletions
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d1edaf969b..e950a119d3 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -73,7 +73,7 @@ bool isInitialized();
const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
void set_thread_recorder(class ThreadRecorder*);
-class MasterThreadRecorder& getMasterThreadRecorder();
+class MasterThreadRecorder& getUIThreadRecorder();
// one per thread per type
template<typename ACCUMULATOR>
@@ -148,6 +148,15 @@ public:
}
}
+ void flush()
+ {
+ llassert(mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].flush();
+ }
+ }
+
void makePrimary()
{
LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
@@ -166,10 +175,12 @@ public:
// NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned
size_t reserveSlot()
{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
if (LLTrace::isInitialized())
{
llerrs << "Attempting to declare trace object after program initialization. Trace objects should be statically initialized." << llendl;
}
+#endif
size_t next_slot = sNextStorageSlot++;
if (next_slot >= mStorageSize)
{
@@ -260,14 +271,14 @@ protected:
};
template<typename T>
-class MeasurementAccumulator
+class EventAccumulator
{
public:
typedef T value_t;
typedef F64 mean_t;
- typedef MeasurementAccumulator<T> self_t;
+ typedef EventAccumulator<T> self_t;
- MeasurementAccumulator()
+ EventAccumulator()
: mSum(0),
mMin((std::numeric_limits<T>::max)()),
mMax((std::numeric_limits<T>::min)()),
@@ -277,7 +288,7 @@ public:
mLastValue(0)
{}
- void sample(T value)
+ void record(T value)
{
mNumSamples++;
mSum += value;
@@ -301,17 +312,10 @@ public:
if (other.mNumSamples)
{
mSum += other.mSum;
- if (other.mMin < mMin)
- {
- mMin = other.mMin;
- }
- if (other.mMax > mMax)
- {
- mMax = other.mMax;
- }
- F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
- mNumSamples += other.mNumSamples;
- mMean = mMean * weight + other.mMean * (1.f - weight);
+
+ // NOTE: both conditions will hold first time through
+ if (other.mMin < mMin) { mMin = other.mMin; }
+ if (other.mMax > mMax) { mMax = other.mMax; }
// combine variance (and hence standard deviation) of 2 different sized sample groups using
// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
@@ -333,12 +337,16 @@ public:
else
{
mVarianceSum = (F64)mNumSamples
- * ((((n_1 - 1.f) * v_1)
- + ((n_2 - 1.f) * v_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_1 - 1.f) * v_1)
+ + ((n_2 - 1.f) * v_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));
}
+
+ F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
+ mNumSamples += other.mNumSamples;
+ mMean = mMean * weight + other.mMean * (1.f - weight);
mLastValue = other.mLastValue;
}
}
@@ -347,13 +355,15 @@ public:
{
mNumSamples = 0;
mSum = 0;
- mMin = 0;
- mMax = 0;
+ mMin = std::numeric_limits<T>::max();
+ mMax = std::numeric_limits<T>::min();
mMean = 0;
mVarianceSum = 0;
mLastValue = other ? other->mLastValue : 0;
}
+ void flush() {}
+
T getSum() const { return (T)mSum; }
T getMin() const { return (T)mMin; }
T getMax() const { return (T)mMax; }
@@ -376,6 +386,150 @@ private:
template<typename T>
+class SampleAccumulator
+{
+public:
+ typedef T value_t;
+ typedef F64 mean_t;
+ typedef SampleAccumulator<T> self_t;
+
+ SampleAccumulator()
+ : mSum(0),
+ mMin((std::numeric_limits<T>::max)()),
+ mMax((std::numeric_limits<T>::min)()),
+ mMean(0),
+ mVarianceSum(0),
+ mLastSampleTimeStamp(LLTimer::getTotalSeconds()),
+ mTotalSamplingTime(0),
+ mNumSamples(0),
+ mLastValue(0),
+ mHasValue(false)
+ {}
+
+ void sample(T value)
+ {
+ LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds();
+ LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp;
+ mLastSampleTimeStamp = time_stamp;
+
+ if (mHasValue)
+ {
+ mTotalSamplingTime += delta_time;
+ mSum += (F64)mLastValue * delta_time;
+
+ // NOTE: both conditions will hold first time through
+ if (value < mMin) { mMin = value; }
+ if (value > mMax) { mMax = value; }
+
+ F64 old_mean = mMean;
+ mMean += (delta_time / mTotalSamplingTime) * ((F64)mLastValue - old_mean);
+ mVarianceSum += delta_time * ((F64)mLastValue - old_mean) * ((F64)mLastValue - mMean);
+ }
+
+ mLastValue = value;
+ mNumSamples++;
+ mHasValue = true;
+ }
+
+ void addSamples(const self_t& other)
+ {
+ if (other.mTotalSamplingTime)
+ {
+ mSum += other.mSum;
+
+ // NOTE: both conditions will hold first time through
+ if (other.mMin < mMin) { mMin = other.mMin; }
+ if (other.mMax > mMax) { mMax = other.mMax; }
+
+ // combine variance (and hence standard deviation) of 2 different sized sample groups using
+ // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+ F64 n_1 = mTotalSamplingTime,
+ n_2 = other.mTotalSamplingTime;
+ F64 m_1 = mMean,
+ m_2 = other.mMean;
+ F64 v_1 = mVarianceSum / mTotalSamplingTime,
+ v_2 = other.mVarianceSum / other.mTotalSamplingTime;
+ if (n_1 == 0)
+ {
+ mVarianceSum = other.mVarianceSum;
+ }
+ else if (n_2 == 0)
+ {
+ // variance is unchanged
+ // mVarianceSum = mVarianceSum;
+ }
+ else
+ {
+ mVarianceSum = mTotalSamplingTime
+ * ((((n_1 - 1.f) * v_1)
+ + ((n_2 - 1.f) * v_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));
+ }
+
+ llassert(other.mTotalSamplingTime > 0);
+ F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
+ mNumSamples += other.mNumSamples;
+ mTotalSamplingTime += other.mTotalSamplingTime;
+ mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
+ mLastValue = other.mLastValue;
+ mLastSampleTimeStamp = other.mLastSampleTimeStamp;
+ mHasValue |= other.mHasValue;
+ }
+ }
+
+ void reset(const self_t* other)
+ {
+ mNumSamples = 0;
+ mSum = 0;
+ mMin = std::numeric_limits<T>::max();
+ mMax = std::numeric_limits<T>::min();
+ mMean = other ? other->mLastValue : 0;
+ mVarianceSum = 0;
+ mLastSampleTimeStamp = LLTimer::getTotalSeconds();
+ mTotalSamplingTime = 0;
+ mLastValue = other ? other->mLastValue : 0;
+ mHasValue = other ? other->mHasValue : false;
+ }
+
+ void flush()
+ {
+ LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds();
+ LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp;
+
+ mSum += (F64)mLastValue * delta_time;
+
+ mTotalSamplingTime += delta_time;
+ mLastSampleTimeStamp = time_stamp;
+ }
+
+ T getSum() const { return (T)mSum; }
+ T getMin() const { return (T)mMin; }
+ T getMax() const { return (T)mMax; }
+ T getLastValue() const { return (T)mLastValue; }
+ F64 getMean() const { return mMean; }
+ F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mTotalSamplingTime); }
+ U32 getSampleCount() const { return mNumSamples; }
+
+private:
+ T mSum,
+ mMin,
+ mMax,
+ mLastValue;
+
+ bool mHasValue;
+
+ F64 mMean,
+ mVarianceSum;
+
+ LLUnitImplicit<LLUnits::Seconds, F64> mLastSampleTimeStamp,
+ mTotalSamplingTime;
+
+ U32 mNumSamples;
+};
+
+template<typename T>
class CountAccumulator
{
public:
@@ -406,6 +560,8 @@ public:
mSum = 0;
}
+ void flush() {}
+
T getSum() const { return (T)mSum; }
U32 getSampleCount() const { return mNumSamples; }
@@ -439,6 +595,7 @@ public:
TimeBlockAccumulator();
void addSamples(const self_t& other);
void reset(const self_t* other);
+ void flush() {}
//
// members
@@ -493,25 +650,44 @@ public:
template <typename T = F64>
-class MeasurementStatHandle
-: public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
+class EventStatHandle
+: public TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
{
public:
typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
- typedef TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
+ typedef TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
- MeasurementStatHandle(const char* name, const char* description = NULL)
+ EventStatHandle(const char* name, const char* description = NULL)
: trace_t(name, description)
{}
};
template<typename T, typename VALUE_T>
-void sample(MeasurementStatHandle<T>& measurement, VALUE_T value)
+void record(EventStatHandle<T>& measurement, VALUE_T value)
{
T converted_value(value);
- measurement.getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value));
+ measurement.getPrimaryAccumulator()->record(LLUnits::rawValue(converted_value));
}
+template <typename T = F64>
+class SampleStatHandle
+: public TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
+{
+public:
+ typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
+ typedef TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
+
+ SampleStatHandle(const char* name, const char* description = NULL)
+ : trace_t(name, description)
+ {}
+};
+
+template<typename T, typename VALUE_T>
+void sample(SampleStatHandle<T>& measurement, VALUE_T value)
+{
+ T converted_value(value);
+ measurement.getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value));
+}
template <typename T = F64>
class CountStatHandle
@@ -560,6 +736,8 @@ struct MemStatAccumulator
mDeallocatedCount = 0;
}
+ void flush() {}
+
size_t mSize,
mChildSize;
int mAllocatedCount,