diff options
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/llcriticaldamp.cpp | 77 | ||||
-rw-r--r-- | indra/llcommon/llcriticaldamp.h | 32 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 1 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 185 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 46 | ||||
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.cpp | 32 | ||||
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.h | 6 |
7 files changed, 209 insertions, 170 deletions
diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp index 87d79b1ee0..59a31bf9df 100644 --- a/indra/llcommon/llcriticaldamp.cpp +++ b/indra/llcommon/llcriticaldamp.cpp @@ -27,18 +27,38 @@ #include "linden_common.h" #include "llcriticaldamp.h" +#include <algorithm> //----------------------------------------------------------------------------- // static members //----------------------------------------------------------------------------- -LLFrameTimer LLCriticalDamp::sInternalTimer; -std::map<F32, F32> LLCriticalDamp::sInterpolants; -F32 LLCriticalDamp::sTimeDelta; +LLFrameTimer LLSmoothInterpolation::sInternalTimer; +std::vector<LLSmoothInterpolation::Interpolant> LLSmoothInterpolation::sInterpolants; +F32 LLSmoothInterpolation::sTimeDelta; + +// helper functors +struct LLSmoothInterpolation::CompareTimeConstants +{ + bool operator()(const F32& a, const LLSmoothInterpolation::Interpolant& b) const + { + return a < b.mTimeScale; + } + + bool operator()(const LLSmoothInterpolation::Interpolant& a, const F32& b) const + { + return a.mTimeScale < b; // bottom of a is higher than bottom of b + } + + bool operator()(const LLSmoothInterpolation::Interpolant& a, const LLSmoothInterpolation::Interpolant& b) const + { + return a.mTimeScale < b.mTimeScale; // bottom of a is higher than bottom of b + } +}; //----------------------------------------------------------------------------- -// LLCriticalDamp() +// LLSmoothInterpolation() //----------------------------------------------------------------------------- -LLCriticalDamp::LLCriticalDamp() +LLSmoothInterpolation::LLSmoothInterpolation() { sTimeDelta = 0.f; } @@ -47,43 +67,54 @@ LLCriticalDamp::LLCriticalDamp() //----------------------------------------------------------------------------- // updateInterpolants() //----------------------------------------------------------------------------- -void LLCriticalDamp::updateInterpolants() +void LLSmoothInterpolation::updateInterpolants() { sTimeDelta = sInternalTimer.getElapsedTimeAndResetF32(); - F32 time_constant; - - for (std::map<F32, F32>::iterator iter = sInterpolants.begin(); - iter != sInterpolants.end(); iter++) + for (S32 i = 0; i < sInterpolants.size(); i++) { - time_constant = iter->first; - F32 new_interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant); - new_interpolant = llclamp(new_interpolant, 0.f, 1.f); - sInterpolants[time_constant] = new_interpolant; + Interpolant& interp = sInterpolants[i]; + interp.mInterpolant = calcInterpolant(interp.mTimeScale); } } //----------------------------------------------------------------------------- // getInterpolant() //----------------------------------------------------------------------------- -F32 LLCriticalDamp::getInterpolant(const F32 time_constant, BOOL use_cache) +F32 LLSmoothInterpolation::getInterpolant(LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache) { if (time_constant == 0.f) { return 1.f; } - if (use_cache && sInterpolants.count(time_constant)) + if (use_cache) { - return sInterpolants[time_constant]; + interpolant_vec_t::iterator find_it = std::lower_bound(sInterpolants.begin(), sInterpolants.end(), time_constant.value(), CompareTimeConstants()); + if (find_it != sInterpolants.end() && find_it->mTimeScale == time_constant) + { + return find_it->mInterpolant; + } + else + { + Interpolant interp; + interp.mTimeScale = time_constant.value(); + interp.mInterpolant = calcInterpolant(time_constant.value()); + sInterpolants.insert(find_it, interp); + return interp.mInterpolant; + } } - - F32 interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant); - interpolant = llclamp(interpolant, 0.f, 1.f); - if (use_cache) + else { - sInterpolants[time_constant] = interpolant; + return calcInterpolant(time_constant.value()); + } +} - return interpolant; +//----------------------------------------------------------------------------- +// getInterpolant() +//----------------------------------------------------------------------------- +F32 LLSmoothInterpolation::calcInterpolant(F32 time_constant) +{ + return llclamp(1.f - pow(2.f, -sTimeDelta / time_constant), 0.f, 1.f); } diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h index 52f052ae25..ab5d4ba6e2 100644 --- a/indra/llcommon/llcriticaldamp.h +++ b/indra/llcommon/llcriticaldamp.h @@ -28,26 +28,46 @@ #ifndef LL_LLCRITICALDAMP_H #define LL_LLCRITICALDAMP_H -#include <map> +#include <vector> #include "llframetimer.h" +#include "llunit.h" -class LL_COMMON_API LLCriticalDamp +class LL_COMMON_API LLSmoothInterpolation { public: - LLCriticalDamp(); + LLSmoothInterpolation(); // MANIPULATORS static void updateInterpolants(); // ACCESSORS - static F32 getInterpolant(const F32 time_constant, BOOL use_cache = TRUE); + static F32 getInterpolant(LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache = true); -protected: + template<typename T> + static T lerp(T a, T b, LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache = true) + { + F32 interpolant = getInterpolant(time_constant, use_cache); + return ((a * (1.f - interpolant)) + + (b * interpolant)); + } + +protected: + static F32 calcInterpolant(F32 time_constant); + + struct CompareTimeConstants; static LLFrameTimer sInternalTimer; // frame timer for calculating deltas - static std::map<F32, F32> sInterpolants; + struct Interpolant + { + F32 mTimeScale; + F32 mInterpolant; + }; + typedef std::vector<Interpolant> interpolant_vec_t; + static interpolant_vec_t sInterpolants; static F32 sTimeDelta; }; +typedef LLSmoothInterpolation LLCriticalDamp; + #endif // LL_LLCRITICALDAMP_H diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index 44da1939c6..9bca3625b6 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -287,6 +287,7 @@ public: { mNumSamples++; mSum += value; + // NOTE: both conditions will hold on first pass through if (value < mMin) { mMin = value; diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index ab8dbce2ce..259f5a7a27 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -34,13 +34,13 @@ namespace LLTrace { + /////////////////////////////////////////////////////////////////////// -// Recording +// RecordingBuffers /////////////////////////////////////////////////////////////////////// -Recording::Recording() -: mElapsedSeconds(0), - mCountsFloat(new AccumulatorBuffer<CountAccumulator<F64> >()), +RecordingBuffers::RecordingBuffers() +: mCountsFloat(new AccumulatorBuffer<CountAccumulator<F64> >()), mMeasurementsFloat(new AccumulatorBuffer<MeasurementAccumulator<F64> >()), mCounts(new AccumulatorBuffer<CountAccumulator<S64> >()), mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<S64> >()), @@ -48,71 +48,7 @@ Recording::Recording() mMemStats(new AccumulatorBuffer<MemStatAccumulator>()) {} -Recording::Recording( const Recording& other ) -{ - llassert(other.mCountsFloat.notNull()); - mSamplingTimer = other.mSamplingTimer; - mElapsedSeconds = other.mElapsedSeconds; - mCountsFloat = other.mCountsFloat; - mMeasurementsFloat = other.mMeasurementsFloat; - mCounts = other.mCounts; - mMeasurements = other.mMeasurements; - mStackTimers = other.mStackTimers; - mMemStats = other.mMemStats; - - LLStopWatchControlsMixin<Recording>::setPlayState(other.getPlayState()); -} - - -Recording::~Recording() -{ - stop(); - llassert(isStopped()); -} - -void Recording::update() -{ - if (isStarted()) - { - LLTrace::get_thread_recorder()->update(this); - mSamplingTimer.reset(); - } -} - -void Recording::handleReset() -{ - mCountsFloat.write()->reset(); - mMeasurementsFloat.write()->reset(); - mCounts.write()->reset(); - mMeasurements.write()->reset(); - mStackTimers.write()->reset(); - mMemStats.write()->reset(); - - mElapsedSeconds = 0.0; - mSamplingTimer.reset(); -} - -void Recording::handleStart() -{ - mSamplingTimer.reset(); - LLTrace::get_thread_recorder()->activate(this); -} - -void Recording::handleStop() -{ - mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); - LLTrace::TimeBlock::processTimes(); - LLTrace::get_thread_recorder()->deactivate(this); -} - -void Recording::handleSplitTo(Recording& other) -{ - stop(); - other.restart(); - syncTo(other); -} - -void Recording::syncTo(Recording& other) +void RecordingBuffers::handOffTo(RecordingBuffers& other) { other.mCountsFloat.write()->reset(mCountsFloat); other.mMeasurementsFloat.write()->reset(mMeasurementsFloat); @@ -122,7 +58,7 @@ void Recording::syncTo(Recording& other) other.mMemStats.write()->reset(mMemStats); } -void Recording::makePrimary() +void RecordingBuffers::makePrimary() { mCountsFloat.write()->makePrimary(); mMeasurementsFloat.write()->makePrimary(); @@ -144,12 +80,12 @@ void Recording::makePrimary() } } -bool Recording::isPrimary() const +bool RecordingBuffers::isPrimary() const { return mCounts->isPrimary(); } -void Recording::makeUnique() +void RecordingBuffers::makeUnique() { mCountsFloat.makeUnique(); mMeasurementsFloat.makeUnique(); @@ -159,19 +95,17 @@ void Recording::makeUnique() mMemStats.makeUnique(); } -void Recording::appendRecording( const Recording& other ) +void RecordingBuffers::appendBuffers( const RecordingBuffers& other ) { mCountsFloat.write()->addSamples(*other.mCountsFloat); mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat); mCounts.write()->addSamples(*other.mCounts); mMeasurements.write()->addSamples(*other.mMeasurements); mMemStats.write()->addSamples(*other.mMemStats); - mStackTimers.write()->addSamples(*other.mStackTimers); - mElapsedSeconds += other.mElapsedSeconds; } -void Recording::mergeRecording( const Recording& other) +void RecordingBuffers::mergeBuffers( const RecordingBuffers& other) { mCountsFloat.write()->addSamples(*other.mCountsFloat); mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat); @@ -180,6 +114,84 @@ void Recording::mergeRecording( const Recording& other) mMemStats.write()->addSamples(*other.mMemStats); } +void RecordingBuffers::resetBuffers(RecordingBuffers* other) +{ + mCountsFloat.write()->reset(other ? other->mCountsFloat : NULL); + mMeasurementsFloat.write()->reset(other ? other->mMeasurementsFloat : NULL); + mCounts.write()->reset(other ? other->mCounts : NULL); + mMeasurements.write()->reset(other ? other->mMeasurements : NULL); + mStackTimers.write()->reset(other ? other->mStackTimers : NULL); + mMemStats.write()->reset(other ? other->mMemStats : NULL); +} + +/////////////////////////////////////////////////////////////////////// +// Recording +/////////////////////////////////////////////////////////////////////// + +Recording::Recording() +: mElapsedSeconds(0) +{} + +Recording::Recording( const Recording& other ) +{ + LLStopWatchControlsMixin<Recording>::setPlayState(other.getPlayState()); +} + + +Recording::~Recording() +{ + stop(); + llassert(isStopped()); +} + +void Recording::update() +{ + if (isStarted()) + { + LLTrace::get_thread_recorder()->update(this); + mSamplingTimer.reset(); + } +} + +void Recording::handleReset() +{ + resetBuffers(); + + mElapsedSeconds = 0.0; + mSamplingTimer.reset(); +} + +void Recording::handleStart() +{ + mSamplingTimer.reset(); + LLTrace::get_thread_recorder()->activate(this); +} + +void Recording::handleStop() +{ + mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); + LLTrace::TimeBlock::processTimes(); + LLTrace::get_thread_recorder()->deactivate(this); +} + +void Recording::handleSplitTo(Recording& other) +{ + stop(); + other.restart(); + handOffTo(other); +} + +void Recording::appendRecording( const Recording& other ) +{ + appendBuffers(other); + mElapsedSeconds += other.mElapsedSeconds; +} + +void Recording::mergeRecording( const Recording& other) +{ + mergeBuffers(other); +} + LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const { const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()]; @@ -279,23 +291,6 @@ U32 Recording::getSampleCount( const TraceType<CountAccumulator<S64> >& stat ) c return (*mMeasurementsFloat)[stat.getIndex()].getSampleCount(); } - -F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<F64> >& stat ) const -{ - F64 sum = (*mMeasurementsFloat)[stat.getIndex()].getSum(); - return (sum != 0.0) - ? (sum / mElapsedSeconds) - : 0.0; -} - -F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<S64> >& stat ) const -{ - S64 sum = (*mMeasurements)[stat.getIndex()].getSum(); - return (sum != 0) - ? ((F64)sum / mElapsedSeconds) - : 0.0; -} - F64 Recording::getMin( const TraceType<MeasurementAccumulator<F64> >& stat ) const { return (*mMeasurementsFloat)[stat.getIndex()].getMin(); @@ -356,8 +351,6 @@ U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& st return (*mMeasurements)[stat.getIndex()].getSampleCount(); } - - /////////////////////////////////////////////////////////////////////// // PeriodicRecording /////////////////////////////////////////////////////////////////////// @@ -537,7 +530,7 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other) PeriodicRecording& get_frame_recording() { - static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED)); + static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(1000, PeriodicRecording::STARTED)); return *sRecording; } diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 7a0266529b..01cc835d58 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -100,19 +100,38 @@ private: namespace LLTrace { - class Recording : public LLStopWatchControlsMixin<Recording> + class RecordingBuffers { public: - Recording(); - - Recording(const Recording& other); - ~Recording(); + RecordingBuffers(); + void handOffTo(RecordingBuffers& other); void makePrimary(); bool isPrimary() const; void makeUnique(); + void appendBuffers(const RecordingBuffers& other); + void mergeBuffers(const RecordingBuffers& other); + void resetBuffers(RecordingBuffers* other = NULL); + + protected: + LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > > mCountsFloat; + LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > > mMeasurementsFloat; + LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > > mCounts; + LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > > mMeasurements; + LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> > mStackTimers; + LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> > mMemStats; + }; + + class Recording : public LLStopWatchControlsMixin<Recording>, public RecordingBuffers + { + public: + Recording(); + + Recording(const Recording& other); + ~Recording(); + // accumulate data from subsequent, non-overlapping recording void appendRecording(const Recording& other); @@ -165,14 +184,6 @@ namespace LLTrace return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat)); } - F64 getPerSec(const TraceType<MeasurementAccumulator<F64> >& stat) const; - F64 getPerSec(const TraceType<MeasurementAccumulator<S64> >& stat) const; - template <typename T> - T getPerSec(const MeasurementStatHandle<T>& stat) const - { - return (T)getPerSec(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat)); - } - F64 getMin(const TraceType<MeasurementAccumulator<F64> >& stat) const; S64 getMin(const TraceType<MeasurementAccumulator<S64> >& stat) const; template <typename T> @@ -218,8 +229,6 @@ namespace LLTrace LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); } - void syncTo(Recording& other); - private: friend class ThreadRecorder; @@ -232,13 +241,6 @@ namespace LLTrace // returns data for current thread class ThreadRecorder* getThreadRecorder(); - LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > > mCountsFloat; - LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > > mMeasurementsFloat; - LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > > mCounts; - LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > > mMeasurements; - LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> > mStackTimers; - LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> > mMemStats; - LLTimer mSamplingTimer; F64 mElapsedSeconds; }; diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 113febcca8..9bef040cf7 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -97,11 +97,11 @@ void ThreadRecorder::activate( Recording* recording ) ActiveRecording* active_recording = new ActiveRecording(recording); if (!mActiveRecordings.empty()) { - mActiveRecordings.front()->mBaseline.syncTo(active_recording->mBaseline); + mActiveRecordings.front()->mPartialRecording.handOffTo(active_recording->mPartialRecording); } mActiveRecordings.push_front(active_recording); - mActiveRecordings.front()->mBaseline.makePrimary(); + mActiveRecordings.front()->mPartialRecording.makePrimary(); } ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Recording* recording ) @@ -118,10 +118,10 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Record if (next_it != mActiveRecordings.end()) { // ...push our gathered data down to it - (*next_it)->mBaseline.appendRecording((*it)->mBaseline); + (*next_it)->mPartialRecording.appendBuffers((*it)->mPartialRecording); } - // copy accumulated measurements into result buffer and clear accumulator (mBaseline) + // copy accumulated measurements into result buffer and clear accumulator (mPartialRecording) (*it)->moveBaselineToTarget(); if ((*it)->mTargetRecording == recording) @@ -171,16 +171,8 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target ) void ThreadRecorder::ActiveRecording::moveBaselineToTarget() { - mTargetRecording->mMeasurementsFloat.write()->addSamples(*mBaseline.mMeasurementsFloat); - mTargetRecording->mCountsFloat.write()->addSamples(*mBaseline.mCountsFloat); - mTargetRecording->mMeasurements.write()->addSamples(*mBaseline.mMeasurements); - mTargetRecording->mCounts.write()->addSamples(*mBaseline.mCounts); - mTargetRecording->mStackTimers.write()->addSamples(*mBaseline.mStackTimers); - mBaseline.mMeasurementsFloat.write()->reset(); - mBaseline.mCountsFloat.write()->reset(); - mBaseline.mMeasurements.write()->reset(); - mBaseline.mCounts.write()->reset(); - mBaseline.mStackTimers.write()->reset(); + mTargetRecording->appendBuffers(mPartialRecording); + mPartialRecording.resetBuffers(); } @@ -220,16 +212,16 @@ void SlaveThreadRecorder::SharedData::appendTo( Recording& sink ) sink.appendRecording(mRecording); } -void SlaveThreadRecorder::SharedData::mergeFrom( const Recording& source ) +void SlaveThreadRecorder::SharedData::mergeFrom( const RecordingBuffers& source ) { LLMutexLock lock(&mRecordingMutex); - mRecording.mergeRecording(source); + mRecording.mergeBuffers(source); } -void SlaveThreadRecorder::SharedData::mergeTo( Recording& sink ) +void SlaveThreadRecorder::SharedData::mergeTo( RecordingBuffers& sink ) { LLMutexLock lock(&mRecordingMutex); - sink.mergeRecording(mRecording); + sink.mergeBuffers(mRecording); } void SlaveThreadRecorder::SharedData::reset() @@ -251,13 +243,13 @@ void MasterThreadRecorder::pullFromSlaveThreads() LLMutexLock lock(&mSlaveListMutex); - Recording& target_recording = mActiveRecordings.front()->mBaseline; + RecordingBuffers& target_recording_buffers = mActiveRecordings.front()->mPartialRecording; for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end(); it != end_it; ++it) { // ignore block timing info for now - (*it)->mSharedData.mergeTo(target_recording); + (*it)->mSharedData.mergeTo(target_recording_buffers); (*it)->mSharedData.reset(); } } diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h index 0e6c091900..3e24303d92 100644 --- a/indra/llcommon/lltracethreadrecorder.h +++ b/indra/llcommon/lltracethreadrecorder.h @@ -59,7 +59,7 @@ namespace LLTrace ActiveRecording(Recording* target); Recording* mTargetRecording; - Recording mBaseline; + RecordingBuffers mPartialRecording; void moveBaselineToTarget(); }; @@ -111,8 +111,8 @@ namespace LLTrace public: void appendFrom(const Recording& source); void appendTo(Recording& sink); - void mergeFrom(const Recording& source); - void mergeTo(Recording& sink); + void mergeFrom(const RecordingBuffers& source); + void mergeTo(RecordingBuffers& sink); void reset(); private: LLMutex mRecordingMutex; |