From 9fd3af3c389ed491b515cbb5136b344b069913e4 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 13 Jun 2013 15:29:15 -0700 Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics changed Units macros and argument order to make it more clear optimized units for integer types fixed merging of periodicrecordings...should eliminate duplicate entries in sceneloadmonitor history --- indra/llcharacter/llkeyframewalkmotion.cpp | 2 +- indra/llcommon/llcriticaldamp.cpp | 2 +- indra/llcommon/llcriticaldamp.h | 4 +- indra/llcommon/lldate.cpp | 2 +- indra/llcommon/lldate.h | 2 +- indra/llcommon/llfasttimer.cpp | 14 +- indra/llcommon/llfasttimer.h | 2 +- indra/llcommon/llprocessor.cpp | 2 +- indra/llcommon/llprocessor.h | 2 +- indra/llcommon/lltimer.cpp | 14 +- indra/llcommon/lltimer.h | 16 +- indra/llcommon/lltrace.h | 76 +++--- indra/llcommon/lltracerecording.cpp | 189 ++++++++------- indra/llcommon/lltracerecording.h | 56 ++--- indra/llcommon/llunit.h | 372 ++++++++++++++++++----------- indra/llcommon/tests/llunits_test.cpp | 104 ++++---- indra/llrender/llimagegl.cpp | 6 +- indra/llrender/llimagegl.h | 6 +- indra/llui/llstatbar.cpp | 4 +- indra/newview/llappviewer.cpp | 2 +- indra/newview/llappviewer.h | 2 +- indra/newview/llfasttimerview.cpp | 303 ++++++++++++----------- indra/newview/llfasttimerview.h | 77 +++--- indra/newview/llscenemonitor.cpp | 4 +- indra/newview/lltexturefetch.h | 2 +- indra/newview/lltextureview.cpp | 12 +- indra/newview/llviewerassetstats.cpp | 4 +- indra/newview/llviewerassetstats.h | 2 +- indra/newview/llviewermessage.cpp | 18 +- indra/newview/llviewerstats.cpp | 10 +- indra/newview/llviewerstats.h | 6 +- indra/newview/llviewertexture.cpp | 16 +- indra/newview/llviewertexture.h | 14 +- indra/newview/llviewerwindow.cpp | 2 +- indra/newview/pipeline.cpp | 2 +- 35 files changed, 735 insertions(+), 616 deletions(-) (limited to 'indra') diff --git a/indra/llcharacter/llkeyframewalkmotion.cpp b/indra/llcharacter/llkeyframewalkmotion.cpp index e188b06c03..c6ca0b542e 100755 --- a/indra/llcharacter/llkeyframewalkmotion.cpp +++ b/indra/llcharacter/llkeyframewalkmotion.cpp @@ -383,7 +383,7 @@ BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask) F32 target_roll = llclamp(ang_vel.mV[VZ], -4.f, 4.f) * roll_factor; // roll is critically damped interpolation between current roll and angular velocity-derived target roll - mRoll = LLSmoothInterpolation::lerp(mRoll, target_roll, LLUnit(100)); + mRoll = LLSmoothInterpolation::lerp(mRoll, target_roll, LLUnit(100)); LLQuaternion roll(mRoll, LLVector3(0.f, 0.f, 1.f)); mPelvisState->setRotation(roll); diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp index 2f013fe255..575fc4149e 100755 --- a/indra/llcommon/llcriticaldamp.cpp +++ b/indra/llcommon/llcriticaldamp.cpp @@ -81,7 +81,7 @@ void LLSmoothInterpolation::updateInterpolants() //----------------------------------------------------------------------------- // getInterpolant() //----------------------------------------------------------------------------- -F32 LLSmoothInterpolation::getInterpolant(LLUnit time_constant, bool use_cache) +F32 LLSmoothInterpolation::getInterpolant(LLUnit time_constant, bool use_cache) { if (time_constant == 0.f) { diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h index ab5d4ba6e2..e174643cd0 100755 --- a/indra/llcommon/llcriticaldamp.h +++ b/indra/llcommon/llcriticaldamp.h @@ -42,10 +42,10 @@ public: static void updateInterpolants(); // ACCESSORS - static F32 getInterpolant(LLUnit time_constant, bool use_cache = true); + static F32 getInterpolant(LLUnit time_constant, bool use_cache = true); template - static T lerp(T a, T b, LLUnit time_constant, bool use_cache = true) + static T lerp(T a, T b, LLUnit time_constant, bool use_cache = true) { F32 interpolant = getInterpolant(time_constant, use_cache); return ((a * (1.f - interpolant)) diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 2efe39e158..7892269e35 100755 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -55,7 +55,7 @@ LLDate::LLDate(const LLDate& date) : mSecondsSinceEpoch(date.mSecondsSinceEpoch) {} -LLDate::LLDate(LLUnit seconds_since_epoch) : +LLDate::LLDate(LLUnit seconds_since_epoch) : mSecondsSinceEpoch(seconds_since_epoch.value()) {} diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index b62a846147..1067ac5280 100755 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -59,7 +59,7 @@ public: * * @param seconds_since_epoch The number of seconds since UTC epoch. */ - LLDate(LLUnit seconds_since_epoch); + LLDate(LLUnit seconds_since_epoch); /** * @brief Construct a date from a string representation diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index dfc72bd2ce..809a0327ca 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -146,8 +146,8 @@ U64 TimeBlock::countsPerSecond() { #if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS //getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz - static LLUnit sCPUClockFrequency = LLProcessorInfo().getCPUFrequency(); - + static LLUnit sCPUClockFrequency = LLProcessorInfo().getCPUFrequency(); + return sCPUClockFrequency.value(); #else // If we're not using RDTSC, each fasttimer tick is just a performance counter tick. // Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency()) @@ -159,8 +159,8 @@ U64 TimeBlock::countsPerSecond() QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency); firstcall = false; } -#endif return sCPUClockFrequency.value(); +#endif } #endif @@ -318,11 +318,11 @@ void TimeBlock::logStats() LL_DEBUGS("FastTimers") << "LLProcessorInfo().getCPUFrequency() " << LLProcessorInfo().getCPUFrequency() << LL_ENDL; LL_DEBUGS("FastTimers") << "getCPUClockCount32() " << getCPUClockCount32() << LL_ENDL; LL_DEBUGS("FastTimers") << "getCPUClockCount64() " << getCPUClockCount64() << LL_ENDL; - LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64()) / (LLUnit(LLProcessorInfo().getCPUFrequency())) << LL_ENDL; + LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64()) / (LLUnit(LLProcessorInfo().getCPUFrequency())) << LL_ENDL; } call_count++; - LLUnit total_time(0); + LLUnit total_time(0); LLSD sd; { @@ -365,7 +365,7 @@ void TimeBlock::dumpCurTimes() ++it) { TimeBlock* timerp = (*it); - LLUnit total_time_ms = last_frame_recording.getSum(*timerp); + LLUnit total_time_ms = last_frame_recording.getSum(*timerp); U32 num_calls = last_frame_recording.getSum(timerp->callCount()); // Don't bother with really brief times, keep output concise @@ -449,7 +449,7 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other ) } } -LLUnit BlockTimer::getElapsedTime() +LLUnit BlockTimer::getElapsedTime() { U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime; diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 20514d1638..fdc6997d45 100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -71,7 +71,7 @@ public: BlockTimer(TimeBlock& timer); ~BlockTimer(); - LLUnit getElapsedTime(); + LLUnit getElapsedTime(); private: diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 5ddfa6fcef..b80e813d84 100755 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -875,7 +875,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) LLProcessorInfo::~LLProcessorInfo() {} -LLUnitImplicit LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +LLUnitImplicit LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index fbd427f484..7f220467b0 100755 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -37,7 +37,7 @@ public: LLProcessorInfo(); ~LLProcessorInfo(); - LLUnitImplicit getCPUFrequency() const; + LLUnitImplicit getCPUFrequency() const; bool hasSSE() const; bool hasSSE2() const; bool hasAltivec() const; diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 838155d54d..693809b622 100755 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -285,14 +285,14 @@ LLTimer::~LLTimer() } // static -LLUnitImplicit LLTimer::getTotalTime() +LLUnitImplicit LLTimer::getTotalTime() { // simply call into the implementation function. return totalTime(); } // static -LLUnitImplicit LLTimer::getTotalSeconds() +LLUnitImplicit LLTimer::getTotalSeconds() { return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64; } @@ -341,23 +341,23 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount) } -LLUnitImplicit LLTimer::getElapsedTimeF64() const +LLUnitImplicit LLTimer::getElapsedTimeF64() const { U64 last = mLastClockCount; return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv; } -LLUnitImplicit LLTimer::getElapsedTimeF32() const +LLUnitImplicit LLTimer::getElapsedTimeF32() const { return (F32)getElapsedTimeF64(); } -LLUnitImplicit LLTimer::getElapsedTimeAndResetF64() +LLUnitImplicit LLTimer::getElapsedTimeAndResetF64() { return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv; } -LLUnitImplicit LLTimer::getElapsedTimeAndResetF32() +LLUnitImplicit LLTimer::getElapsedTimeAndResetF32() { return (F32)getElapsedTimeAndResetF64(); } @@ -370,7 +370,7 @@ void LLTimer::setTimerExpirySec(F32 expiration) + (U64)((F32)(expiration * gClockFrequency)); } -LLUnitImplicit LLTimer::getRemainingTimeF32() const +LLUnitImplicit LLTimer::getRemainingTimeF32() const { U64 cur_ticks = get_clock_count(); if (cur_ticks > mExpirationTicks) diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 0ba87d1e15..9e464c4b1a 100755 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -67,16 +67,16 @@ public: // Return a high precision number of seconds since the start of // this application instance. - static LLUnitImplicit getElapsedSeconds() + static LLUnitImplicit getElapsedSeconds() { return sTimer->getElapsedTimeF64(); } // Return a high precision usec since epoch - static LLUnitImplicit getTotalTime(); + static LLUnitImplicit getTotalTime(); // Return a high precision seconds since epoch - static LLUnitImplicit getTotalSeconds(); + static LLUnitImplicit getTotalSeconds(); // MANIPULATORS @@ -87,16 +87,16 @@ public: void setTimerExpirySec(F32 expiration); BOOL checkExpirationAndReset(F32 expiration); BOOL hasExpired() const; - LLUnitImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset - LLUnitImplicit getElapsedTimeAndResetF64(); + LLUnitImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset + LLUnitImplicit getElapsedTimeAndResetF64(); - LLUnitImplicit getRemainingTimeF32() const; + LLUnitImplicit getRemainingTimeF32() const; static BOOL knownBadTimer(); // ACCESSORS - LLUnitImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds - LLUnitImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds + LLUnitImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds + LLUnitImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds bool getStarted() const { return mStarted; } diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index cfe1273b4b..1bf853c5c0 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -44,27 +44,27 @@ namespace LLTrace { class Recording; -typedef LLUnit Bytes; -typedef LLUnit Kibibytes; -typedef LLUnit Mibibytes; -typedef LLUnit Gibibytes; -typedef LLUnit Bits; -typedef LLUnit Kibibits; -typedef LLUnit Mibibits; -typedef LLUnit Gibibits; - -typedef LLUnit Seconds; -typedef LLUnit Milliseconds; -typedef LLUnit Minutes; -typedef LLUnit Hours; -typedef LLUnit Milliseconds; -typedef LLUnit Microseconds; -typedef LLUnit Nanoseconds; - -typedef LLUnit Meters; -typedef LLUnit Kilometers; -typedef LLUnit Centimeters; -typedef LLUnit Millimeters; +typedef LLUnit Bytes; +typedef LLUnit Kibibytes; +typedef LLUnit Mibibytes; +typedef LLUnit Gibibytes; +typedef LLUnit Bits; +typedef LLUnit Kibibits; +typedef LLUnit Mibibits; +typedef LLUnit Gibibits; + +typedef LLUnit Seconds; +typedef LLUnit Milliseconds; +typedef LLUnit Minutes; +typedef LLUnit Hours; +typedef LLUnit Milliseconds; +typedef LLUnit Microseconds; +typedef LLUnit Nanoseconds; + +typedef LLUnit Meters; +typedef LLUnit Kilometers; +typedef LLUnit Centimeters; +typedef LLUnit Millimeters; void init(); void cleanup(); @@ -216,6 +216,11 @@ public: } size_t size() const + { + return getNumIndices(); + } + + static size_t getNumIndices() { return sNextStorageSlot; } @@ -263,6 +268,7 @@ public: } size_t getIndex() const { return mAccumulatorIndex; } + static size_t getNumIndices() { return AccumulatorBuffer::getNumIndices(); } virtual const char* getUnitLabel() { return ""; } @@ -408,8 +414,8 @@ public: void sample(F64 value) { - LLUnitImplicit time_stamp = LLTimer::getTotalSeconds(); - LLUnitImplicit delta_time = time_stamp - mLastSampleTimeStamp; + LLUnitImplicit time_stamp = LLTimer::getTotalSeconds(); + LLUnitImplicit delta_time = time_stamp - mLastSampleTimeStamp; mLastSampleTimeStamp = time_stamp; if (mHasValue) @@ -498,8 +504,8 @@ public: void flush() { - LLUnitImplicit time_stamp = LLTimer::getTotalSeconds(); - LLUnitImplicit delta_time = time_stamp - mLastSampleTimeStamp; + LLUnitImplicit time_stamp = LLTimer::getTotalSeconds(); + LLUnitImplicit delta_time = time_stamp - mLastSampleTimeStamp; if (mHasValue) { @@ -528,7 +534,7 @@ private: F64 mMean, mVarianceSum; - LLUnitImplicit mLastSampleTimeStamp, + LLUnitImplicit mLastSampleTimeStamp, mTotalSamplingTime; U32 mNumSamples; @@ -578,8 +584,8 @@ private: class TimeBlockAccumulator { public: - typedef LLUnit value_t; - typedef LLUnit mean_t; + typedef LLUnit value_t; + typedef LLUnit mean_t; typedef TimeBlockAccumulator self_t; // fake classes that allows us to view different facets of underlying statistic @@ -591,8 +597,8 @@ public: struct SelfTimeFacet { - typedef LLUnit value_t; - typedef LLUnit mean_t; + typedef LLUnit value_t; + typedef LLUnit mean_t; }; TimeBlockAccumulator(); @@ -672,7 +678,7 @@ template void record(EventStatHandle& measurement, VALUE_T value) { T converted_value(value); - measurement.getPrimaryAccumulator()->record(LLUnits::rawValue(converted_value)); + measurement.getPrimaryAccumulator()->record(LLUnits::storageValue(converted_value)); } template @@ -694,7 +700,7 @@ template void sample(SampleStatHandle& measurement, VALUE_T value) { T converted_value(value); - measurement.getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value)); + measurement.getPrimaryAccumulator()->sample(LLUnits::storageValue(converted_value)); } template @@ -716,7 +722,7 @@ template void add(CountStatHandle& count, VALUE_T value) { T converted_value(value); - count.getPrimaryAccumulator()->add(LLUnits::rawValue(converted_value)); + count.getPrimaryAccumulator()->add(LLUnits::storageValue(converted_value)); } @@ -739,8 +745,8 @@ struct MemStatAccumulator struct ChildMemFacet { - typedef LLUnit value_t; - typedef LLUnit mean_t; + typedef LLUnit value_t; + typedef LLUnit mean_t; }; MemStatAccumulator() diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index d32504b014..ff90da3822 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -186,26 +186,18 @@ void Recording::handleSplitTo(Recording& other) void Recording::appendRecording( const Recording& other ) { - EPlayState play_state = getPlayState(); - { - pause(); - mBuffers.write()->append(*other.mBuffers); - mElapsedSeconds += other.mElapsedSeconds; - } - setPlayState(play_state); + update(); + mBuffers.write()->append(*other.mBuffers); + mElapsedSeconds += other.mElapsedSeconds; } void Recording::mergeRecording( const Recording& other) { - EPlayState play_state = getPlayState(); - { - pause(); - mBuffers.write()->merge(*other.mBuffers); - } - setPlayState(play_state); + update(); + mBuffers.write()->merge(*other.mBuffers); } -LLUnit Recording::getSum(const TraceType& stat) +LLUnit Recording::getSum(const TraceType& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; update(); @@ -213,7 +205,7 @@ LLUnit Recording::getSum(const TraceType Recording::getSum(const TraceType& stat) +LLUnit Recording::getSum(const TraceType& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; update(); @@ -227,85 +219,85 @@ U32 Recording::getSum(const TraceType& sta return mBuffers->mStackTimers[stat.getIndex()].mCalls; } -LLUnit Recording::getPerSec(const TraceType& stat) +LLUnit Recording::getPerSec(const TraceType& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; update(); return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) - / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); + / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()); } -LLUnit Recording::getPerSec(const TraceType& stat) +LLUnit Recording::getPerSec(const TraceType& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; update(); return (F64)(accumulator.mSelfTimeCounter) - / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); + / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()); } F32 Recording::getPerSec(const TraceType& stat) { update(); - return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds; + return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value(); } -LLUnit Recording::getMin(const TraceType& stat) +LLUnit Recording::getMin(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMin(); } -LLUnit Recording::getMean(const TraceType& stat) +LLUnit Recording::getMean(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMean(); } -LLUnit Recording::getMax(const TraceType& stat) +LLUnit Recording::getMax(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMax(); } -LLUnit Recording::getStandardDeviation(const TraceType& stat) +LLUnit Recording::getStandardDeviation(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation(); } -LLUnit Recording::getLastValue(const TraceType& stat) +LLUnit Recording::getLastValue(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue(); } -LLUnit Recording::getMin(const TraceType& stat) +LLUnit Recording::getMin(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin(); } -LLUnit Recording::getMean(const TraceType& stat) +LLUnit Recording::getMean(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean(); } -LLUnit Recording::getMax(const TraceType& stat) +LLUnit Recording::getMax(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax(); } -LLUnit Recording::getStandardDeviation(const TraceType& stat) +LLUnit Recording::getStandardDeviation(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation(); } -LLUnit Recording::getLastValue(const TraceType& stat) +LLUnit Recording::getLastValue(const TraceType& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue(); @@ -341,7 +333,7 @@ F64 Recording::getPerSec( const TraceType& stat ) update(); F64 sum = mBuffers->mCounts[stat.getIndex()].getSum(); return (sum != 0.0) - ? (sum / mElapsedSeconds) + ? (sum / mElapsedSeconds.value()) : 0.0; } @@ -430,6 +422,7 @@ U32 Recording::getSampleCount( const TraceType& stat ) PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state) : mAutoResize(num_periods == 0), mCurPeriod(0), + mNumPeriods(0), mRecordingPeriods(num_periods ? num_periods : 1) { setPlayState(state); @@ -443,9 +436,20 @@ void PeriodicRecording::nextPeriod() } Recording& old_recording = getCurRecording(); - mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size(); old_recording.splitTo(getCurRecording()); + + mNumPeriods = llmin(mRecordingPeriods.size(), mNumPeriods + 1); +} + +void PeriodicRecording::appendRecording(Recording& recording) +{ + // if I have a recording of any length, then close it off and start a fresh one + if (getCurRecording().getDuration().value()) + { + nextPeriod(); + } + getCurRecording().appendRecording(recording); } @@ -453,77 +457,77 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) { if (other.mRecordingPeriods.empty()) return; - EPlayState play_state = getPlayState(); - pause(); - - EPlayState other_play_state = other.getPlayState(); - other.pause(); - - U32 other_recording_count = other.mRecordingPeriods.size(); - - Recording& other_oldest_recording = other.mRecordingPeriods[(other.mCurPeriod + 1) % other.mRecordingPeriods.size()]; + getCurRecording().update(); + other.getCurRecording().update(); // if I have a recording of any length, then close it off and start a fresh one if (getCurRecording().getDuration().value()) { nextPeriod(); } - getCurRecording().appendRecording(other_oldest_recording); - if (other_recording_count > 1) + if (mAutoResize) { - if (mAutoResize) + S32 other_index = (other.mCurPeriod + 1) % other.mRecordingPeriods.size(); + S32 end_index = (other.mCurPeriod) % other.mRecordingPeriods.size(); + + do { - for (S32 other_index = (other.mCurPeriod + 2) % other_recording_count, - end_index = (other.mCurPeriod + 1) % other_recording_count; - other_index != end_index; - other_index = (other_index + 1) % other_recording_count) + if (other.mRecordingPeriods[other_index].getDuration().value()) { - llassert(other.mRecordingPeriods[other_index].getDuration() != 0.f - && (mRecordingPeriods.empty() - || other.mRecordingPeriods[other_index].getDuration() != mRecordingPeriods.back().getDuration())); mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]); } - - mCurPeriod = mRecordingPeriods.size() - 1; + other_index = (other_index + 1) % other.mRecordingPeriods.size(); } - else + while(other_index != end_index); + + mCurPeriod = mRecordingPeriods.size() - 1; + mNumPeriods = mRecordingPeriods.size(); + } + else + { + //FIXME: get proper number of recordings from other...might not have used all its slots + size_t num_to_copy = llmin( mRecordingPeriods.size(), other.getNumRecordedPeriods()); + std::vector::iterator src_it = other.mRecordingPeriods.begin() + + ( (other.mCurPeriod + 1 // oldest period + + (other.mRecordingPeriods.size() - num_to_copy)) // minus room for copy + % other.mRecordingPeriods.size()); + std::vector::iterator dest_it = mRecordingPeriods.begin() + mCurPeriod; + + for(size_t i = 0; i < num_to_copy; i++) { - size_t num_to_copy = llmin( mRecordingPeriods.size(), other.mRecordingPeriods.size() - 1); - std::vector::iterator src_it = other.mRecordingPeriods.begin() - + ( (other.mCurPeriod + 1 // oldest period - + (other.mRecordingPeriods.size() - num_to_copy)) // minus room for copy - % other.mRecordingPeriods.size()); - std::vector::iterator dest_it = mRecordingPeriods.begin() + ((mCurPeriod + 1) % mRecordingPeriods.size()); - - for(S32 i = 0; i < num_to_copy; i++) - { - *dest_it = *src_it; + *dest_it = *src_it; - if (++src_it == other.mRecordingPeriods.end()) - { - src_it = other.mRecordingPeriods.begin(); - } + if (++src_it == other.mRecordingPeriods.end()) + { + src_it = other.mRecordingPeriods.begin(); + } - if (++dest_it == mRecordingPeriods.end()) - { - dest_it = mRecordingPeriods.begin(); - } + if (++dest_it == mRecordingPeriods.end()) + { + dest_it = mRecordingPeriods.begin(); } - - mCurPeriod = (mCurPeriod + num_to_copy) % mRecordingPeriods.size(); } + + // want argument to % to be positive, otherwise result could be negative and thus out of bounds + llassert(num_to_copy >= 1); + // advance to last recording period copied, so we can check if the last period had actually carried any data, in which case we'll advance below + // using nextPeriod() which retains continuity (mLastValue, etc) + mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size(); + mNumPeriods = llmin(mRecordingPeriods.size(), mNumPeriods + num_to_copy); } - nextPeriod(); - - setPlayState(play_state); - other.setPlayState(other_play_state); + if (getCurRecording().getDuration().value()) + { + //call this to chain last period copied to new active period + nextPeriod(); + } + getCurRecording().setPlayState(getPlayState()); } -LLUnit PeriodicRecording::getDuration() const +LLUnit PeriodicRecording::getDuration() const { - LLUnit duration; + LLUnit duration; size_t num_periods = mRecordingPeriods.size(); for (size_t i = 1; i <= num_periods; i++) { @@ -615,7 +619,7 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other) F64 PeriodicRecording::getPeriodMean( const TraceType& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 mean = 0; if (num_periods <= 0) { return mean; } @@ -643,7 +647,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType& stat, s F64 PeriodicRecording::getPeriodMin( const TraceType& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 min_val = std::numeric_limits::max(); for (S32 i = 1; i <= num_periods; i++) @@ -657,7 +661,7 @@ F64 PeriodicRecording::getPeriodMin( const TraceType& stat, si F64 PeriodicRecording::getPeriodMax( const TraceType& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 max_val = std::numeric_limits::min(); for (S32 i = 1; i <= num_periods; i++) @@ -671,7 +675,7 @@ F64 PeriodicRecording::getPeriodMax( const TraceType& stat, si F64 PeriodicRecording::getPeriodMin( const TraceType& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 min_val = std::numeric_limits::max(); for (S32 i = 1; i <= num_periods; i++) @@ -685,7 +689,7 @@ F64 PeriodicRecording::getPeriodMin( const TraceType& stat, s F64 PeriodicRecording::getPeriodMax(const TraceType& stat, size_t num_periods /*= U32_MAX*/) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 max_val = std::numeric_limits::min(); for (S32 i = 1; i <= num_periods; i++) @@ -700,9 +704,9 @@ F64 PeriodicRecording::getPeriodMax(const TraceType& stat, si F64 PeriodicRecording::getPeriodMean( const TraceType& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - LLUnit total_duration = 0.f; + LLUnit total_duration = 0.f; F64 mean = 0; if (num_periods <= 0) { return mean; } @@ -712,7 +716,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType& stat, S32 index = (mCurPeriod + total_periods - i) % total_periods; if (mRecordingPeriods[index].getDuration() > 0.f) { - LLUnit recording_duration = mRecordingPeriods[index].getDuration(); + LLUnit recording_duration = mRecordingPeriods[index].getDuration(); mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value(); total_duration += recording_duration; } @@ -734,13 +738,11 @@ F64 PeriodicRecording::getPeriodMean( const TraceType& stat, void ExtendableRecording::extend() { // stop recording to get latest data - mPotentialRecording.stop(); + mPotentialRecording.update(); // push the data back to accepted recording mAcceptedRecording.appendRecording(mPotentialRecording); // flush data, so we can start from scratch mPotentialRecording.reset(); - // go back to play state we were in initially - mPotentialRecording.setPlayState(getPlayState()); } void ExtendableRecording::handleStart() @@ -777,15 +779,10 @@ ExtendablePeriodicRecording::ExtendablePeriodicRecording() void ExtendablePeriodicRecording::extend() { - llassert(mPotentialRecording.getPlayState() == getPlayState()); - // stop recording to get latest data - mPotentialRecording.pause(); // push the data back to accepted recording mAcceptedRecording.appendPeriodicRecording(mPotentialRecording); // flush data, so we can start from scratch mPotentialRecording.reset(); - // go back to play state we were in initially - mPotentialRecording.setPlayState(getPlayState()); } diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 4651bfcb61..e3cef77b06 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -148,26 +148,26 @@ namespace LLTrace void makeUnique() { mBuffers.makeUnique(); } // Timer accessors - LLUnit getSum(const TraceType& stat); - LLUnit getSum(const TraceType& stat); + LLUnit getSum(const TraceType& stat); + LLUnit getSum(const TraceType& stat); U32 getSum(const TraceType& stat); - LLUnit getPerSec(const TraceType& stat); - LLUnit getPerSec(const TraceType& stat); + LLUnit getPerSec(const TraceType& stat); + LLUnit getPerSec(const TraceType& stat); F32 getPerSec(const TraceType& stat); // Memory accessors - LLUnit getMin(const TraceType& stat); - LLUnit getMean(const TraceType& stat); - LLUnit getMax(const TraceType& stat); - LLUnit getStandardDeviation(const TraceType& stat); - LLUnit getLastValue(const TraceType& stat); - - LLUnit getMin(const TraceType& stat); - LLUnit getMean(const TraceType& stat); - LLUnit getMax(const TraceType& stat); - LLUnit getStandardDeviation(const TraceType& stat); - LLUnit getLastValue(const TraceType& stat); + LLUnit getMin(const TraceType& stat); + LLUnit getMean(const TraceType& stat); + LLUnit getMax(const TraceType& stat); + LLUnit getStandardDeviation(const TraceType& stat); + LLUnit getLastValue(const TraceType& stat); + + LLUnit getMin(const TraceType& stat); + LLUnit getMean(const TraceType& stat); + LLUnit getMax(const TraceType& stat); + LLUnit getStandardDeviation(const TraceType& stat); + LLUnit getLastValue(const TraceType& stat); U32 getSum(const TraceType& stat); U32 getSum(const TraceType& stat); @@ -273,7 +273,7 @@ namespace LLTrace U32 getSampleCount(const TraceType& stat); - LLUnit getDuration() const { return LLUnit(mElapsedSeconds); } + LLUnit getDuration() const { return mElapsedSeconds; } protected: friend class ThreadRecorder; @@ -288,7 +288,7 @@ namespace LLTrace class ThreadRecorder* getThreadRecorder(); LLTimer mSamplingTimer; - F64 mElapsedSeconds; + LLUnit mElapsedSeconds; LLCopyOnWritePointer mBuffers; }; @@ -299,11 +299,12 @@ namespace LLTrace PeriodicRecording(U32 num_periods, EPlayState state = STOPPED); void nextPeriod(); - U32 getNumPeriods() { return mRecordingPeriods.size(); } + size_t getNumRecordedPeriods() { return mNumPeriods; } - LLUnit getDuration() const; + LLUnit getDuration() const; void appendPeriodicRecording(PeriodicRecording& other); + void appendRecording(Recording& recording); Recording& getLastRecording(); const Recording& getLastRecording() const; Recording& getCurRecording(); @@ -317,7 +318,7 @@ namespace LLTrace typename T::value_t getPeriodMin(const TraceType& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); typename T::value_t min_val = std::numeric_limits::max(); for (S32 i = 1; i <= num_periods; i++) @@ -346,7 +347,7 @@ namespace LLTrace F64 getPeriodMinPerSec(const TraceType& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 min_val = std::numeric_limits::max(); for (S32 i = 1; i <= num_periods; i++) @@ -362,7 +363,7 @@ namespace LLTrace typename T::value_t getPeriodMax(const TraceType& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); typename T::value_t max_val = std::numeric_limits::min(); for (S32 i = 1; i <= num_periods; i++) @@ -391,7 +392,7 @@ namespace LLTrace F64 getPeriodMaxPerSec(const TraceType& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 max_val = std::numeric_limits::min(); for (S32 i = 1; i <= num_periods; i++) @@ -407,7 +408,7 @@ namespace LLTrace typename T::mean_t getPeriodMean(const TraceType& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); typename T::mean_t mean = 0; if (num_periods <= 0) { return mean; } @@ -442,7 +443,7 @@ namespace LLTrace typename T::mean_t getPeriodMeanPerSec(const TraceType& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); typename T::mean_t mean = 0; if (num_periods <= 0) { return mean; } @@ -468,8 +469,9 @@ namespace LLTrace private: std::vector mRecordingPeriods; - const bool mAutoResize; - S32 mCurPeriod; + const bool mAutoResize; + size_t mCurPeriod; + size_t mNumPeriods; }; PeriodicRecording& get_frame_recording(); diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h index f48cbe0e11..5b961c81f0 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -35,31 +35,31 @@ namespace LLUnits { template -struct ConversionFactor +struct Convert { - static F64 get() + static VALUE_TYPE get(VALUE_TYPE val) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(DERIVED_UNITS_TAG, false, "Cannot convert between types."); - return 0; + return val; } }; template -struct ConversionFactor +struct Convert { - static F64 get() + static VALUE_TYPE get(VALUE_TYPE val) { - return 1; + return val; } }; } -template +template struct LLUnit { - typedef LLUnit self_t; + typedef LLUnit self_t; typedef STORAGE_TYPE storage_t; // value initialization @@ -68,11 +68,16 @@ struct LLUnit {} // unit initialization and conversion - template - LLUnit(LLUnit other) + template + LLUnit(LLUnit other) : mValue(convert(other)) {} + bool operator == (const self_t& other) + { + return mValue = other.mValue; + } + // value assignment self_t& operator = (storage_t value) { @@ -81,8 +86,8 @@ struct LLUnit } // unit assignment - template - self_t& operator = (LLUnit other) + template + self_t& operator = (LLUnit other) { mValue = convert(other); return *this; @@ -93,9 +98,9 @@ struct LLUnit return mValue; } - template LLUnit as() + template LLUnit as() { - return LLUnit(*this); + return LLUnit(*this); } @@ -104,8 +109,8 @@ struct LLUnit mValue += value; } - template - void operator += (LLUnit other) + template + void operator += (LLUnit other) { mValue += convert(other); } @@ -115,8 +120,8 @@ struct LLUnit mValue -= value; } - template - void operator -= (LLUnit other) + template + void operator -= (LLUnit other) { mValue -= convert(other); } @@ -127,7 +132,7 @@ struct LLUnit } template - void operator *= (LLUnit multiplicand) + void operator *= (LLUnit multiplicand) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(OTHER_UNIT, false, "Multiplication of unit types not supported."); @@ -139,37 +144,43 @@ struct LLUnit } template - void operator /= (LLUnit divisor) + void operator /= (LLUnit divisor) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(OTHER_UNIT, false, "Illegal in-place division of unit types."); } - template - static storage_t convert(LLUnit v) + template + static storage_t convert(LLUnit v) { - return (storage_t)(v.value() - * LLUnits::ConversionFactor::get() - * LLUnits::ConversionFactor::get()); + return (storage_t)LLUnits::Convert::get((STORAGE_TYPE) + LLUnits::Convert::get(v.value())); } + template + static storage_t convert(LLUnit v) + { + return (storage_t)(v.value()); + } + + protected: storage_t mValue; }; -template -struct LLUnitImplicit : public LLUnit +template +struct LLUnitImplicit : public LLUnit { - typedef LLUnitImplicit self_t; - typedef typename LLUnit::storage_t storage_t; - typedef LLUnit base_t; + typedef LLUnitImplicit self_t; + typedef typename LLUnit::storage_t storage_t; + typedef LLUnit base_t; LLUnitImplicit(storage_t value = storage_t()) : base_t(value) {} - template - LLUnitImplicit(LLUnit other) + template + LLUnitImplicit(LLUnit other) : base_t(convert(other)) {} @@ -184,50 +195,50 @@ struct LLUnitImplicit : public LLUnit // // operator + // -template -LLUnit operator + (LLUnit first, LLUnit second) +template +LLUnit operator + (LLUnit first, LLUnit second) { - LLUnit result(first); + LLUnit result(first); result += second; return result; } -template -LLUnit operator + (LLUnit first, SCALAR_TYPE second) +template +LLUnit operator + (LLUnit first, SCALAR_TYPE second) { - LLUnit result(first); + LLUnit result(first); result += second; return result; } -template -LLUnit operator + (SCALAR_TYPE first, LLUnit second) +template +LLUnit operator + (SCALAR_TYPE first, LLUnit second) { - LLUnit result(first); + LLUnit result(first); result += second; return result; } -template -LLUnitImplicit operator + (LLUnitImplicit first, LLUnit second) +template +LLUnitImplicit operator + (LLUnitImplicit first, LLUnit second) { - LLUnitImplicit result(first); + LLUnitImplicit result(first); result += second; return result; } -template -LLUnitImplicit operator + (LLUnitImplicit first, SCALAR_TYPE second) +template +LLUnitImplicit operator + (LLUnitImplicit first, SCALAR_TYPE second) { - LLUnitImplicit result(first); + LLUnitImplicit result(first); result += second; return result; } -template -LLUnitImplicit operator + (LLUnitImplicit first, LLUnitImplicit second) +template +LLUnitImplicit operator + (LLUnitImplicit first, LLUnitImplicit second) { - LLUnitImplicit result(first); + LLUnitImplicit result(first); result += second; return result; } @@ -235,50 +246,50 @@ LLUnitImplicit operator + (LLUnitImplicit -LLUnit operator - (LLUnit first, LLUnit second) +template +LLUnit operator - (LLUnit first, LLUnit second) { - LLUnit result(first); + LLUnit result(first); result -= second; return result; } -template -LLUnit operator - (LLUnit first, SCALAR_TYPE second) +template +LLUnit operator - (LLUnit first, SCALAR_TYPE second) { - LLUnit result(first); + LLUnit result(first); result -= second; return result; } -template -LLUnit operator - (SCALAR_TYPE first, LLUnit second) +template +LLUnit operator - (SCALAR_TYPE first, LLUnit second) { - LLUnit result(first); + LLUnit result(first); result -= second; return result; } -template -LLUnitImplicit operator - (LLUnitImplicit first, LLUnitImplicit second) +template +LLUnitImplicit operator - (LLUnitImplicit first, LLUnitImplicit second) { - LLUnitImplicit result(first); + LLUnitImplicit result(first); result -= second; return result; } -template -LLUnitImplicit operator - (LLUnitImplicit first, SCALAR_TYPE second) +template +LLUnitImplicit operator - (LLUnitImplicit first, SCALAR_TYPE second) { - LLUnitImplicit result(first); + LLUnitImplicit result(first); result -= second; return result; } -template -LLUnitImplicit operator - (SCALAR_TYPE first, LLUnitImplicit second) +template +LLUnitImplicit operator - (SCALAR_TYPE first, LLUnitImplicit second) { - LLUnitImplicit result(first); + LLUnitImplicit result(first); result -= second; return result; } @@ -286,102 +297,100 @@ LLUnitImplicit operator - (SCALAR_TYPE first, LLUnitImp // // operator * // -template -LLUnit operator * (SCALAR_TYPE first, LLUnit second) +template +LLUnit operator * (SCALAR_TYPE first, LLUnit second) { - return LLUnit((STORAGE_TYPE)(first * second.value())); + return LLUnit((STORAGE_TYPE)(first * second.value())); } -template -LLUnit operator * (LLUnit first, SCALAR_TYPE second) +template +LLUnit operator * (LLUnit first, SCALAR_TYPE second) { - return LLUnit((STORAGE_TYPE)(first.value() * second)); + return LLUnit((STORAGE_TYPE)(first.value() * second)); } -template -LLUnit operator * (LLUnit, LLUnit) +template +LLUnit operator * (LLUnit, LLUnit) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported."); - return LLUnit(); + return LLUnit(); } -template -LLUnitImplicit operator * (SCALAR_TYPE first, LLUnitImplicit second) +template +LLUnitImplicit operator * (SCALAR_TYPE first, LLUnitImplicit second) { - return LLUnitImplicit(first * second.value()); + return LLUnitImplicit(first * second.value()); } -template -LLUnitImplicit operator * (LLUnitImplicit first, SCALAR_TYPE second) +template +LLUnitImplicit operator * (LLUnitImplicit first, SCALAR_TYPE second) { - return LLUnitImplicit(first.value() * second); + return LLUnitImplicit(first.value() * second); } -template -LLUnitImplicit operator * (LLUnitImplicit, LLUnitImplicit) +template +LLUnitImplicit operator * (LLUnitImplicit, LLUnitImplicit) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported."); - return LLUnitImplicit(); + return LLUnitImplicit(); } // // operator / // -template -SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit second) +template +SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit second) { return SCALAR_TYPE(first / second.value()); } -template -LLUnit operator / (LLUnit first, SCALAR_TYPE second) +template +LLUnit operator / (LLUnit first, SCALAR_TYPE second) { - return LLUnit((STORAGE_TYPE)(first.value() / second)); + return LLUnit((STORAGE_TYPE)(first.value() / second)); } -template -STORAGE_TYPE1 operator / (LLUnit first, LLUnit second) +template +STORAGE_TYPE1 operator / (LLUnit first, LLUnit second) { - // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template - return STORAGE_TYPE1(first.value() / second.value()); + return STORAGE_TYPE1(first.value() / first.convert(second)); } -template -LLUnitImplicit operator / (LLUnitImplicit first, SCALAR_TYPE second) +template +LLUnitImplicit operator / (LLUnitImplicit first, SCALAR_TYPE second) { - return LLUnitImplicit((STORAGE_TYPE)(first.value() / second)); + return LLUnitImplicit((STORAGE_TYPE)(first.value() / second)); } -template -STORAGE_TYPE1 operator / (LLUnitImplicit first, LLUnitImplicit second) +template +STORAGE_TYPE1 operator / (LLUnitImplicit first, LLUnitImplicit second) { - // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template - return STORAGE_TYPE1(first.value() / second.value()); + return STORAGE_TYPE1(first.value() / first.convert(second)); } #define COMPARISON_OPERATORS(op) \ -template \ -bool operator op (SCALAR_TYPE first, LLUnit second) \ +template \ +bool operator op (SCALAR_TYPE first, LLUnit second) \ { \ return first op second.value(); \ } \ \ -template \ -bool operator op (LLUnit first, SCALAR_TYPE second) \ +template \ +bool operator op (LLUnit first, SCALAR_TYPE second) \ { \ return first.value() op second; \ } \ \ -template \ -bool operator op (LLUnitImplicit first, LLUnitImplicit second) \ +template \ +bool operator op (LLUnitImplicit first, LLUnitImplicit second) \ { \ return first.value() op first.convert(second); \ } \ \ -template \ - bool operator op (LLUnit first, LLUnit second) \ +template \ + bool operator op (LLUnit first, LLUnit second) \ { \ return first.value() op first.convert(second); \ } @@ -401,7 +410,7 @@ struct LLGetUnitLabel }; template -struct LLGetUnitLabel > +struct LLGetUnitLabel > { static const char* getUnitLabel() { return T::getUnitLabel(); } }; @@ -411,70 +420,147 @@ struct LLGetUnitLabel > // namespace LLUnits { + +template +struct LinearOps +{ + typedef LinearOps self_t; + LinearOps(VALUE_TYPE val) : mValue (val) {} + + operator VALUE_TYPE() const { return mValue; } + VALUE_TYPE mValue; + + template + self_t operator * (T other) + { + return mValue * other; + } + + template + self_t operator / (T other) + { + return mValue / other; + } + + template + self_t operator + (T other) + { + return mValue + other; + } + + template + self_t operator - (T other) + { + return mValue - other; + } +}; + +template +struct InverseLinearOps +{ + typedef InverseLinearOps self_t; + + InverseLinearOps(VALUE_TYPE val) : mValue (val) {} + operator VALUE_TYPE() const { return mValue; } + VALUE_TYPE mValue; + + template + self_t operator * (T other) + { + return mValue / other; + } + + template + self_t operator / (T other) + { + return mValue * other; + } + + template + self_t operator + (T other) + { + return mValue - other; + } + + template + self_t operator - (T other) + { + return mValue + other; + } +}; + + template -T rawValue(T val) { return val; } +T storageValue(T val) { return val; } template -STORAGE_TYPE rawValue(LLUnit val) { return val.value(); } +STORAGE_TYPE storageValue(LLUnit val) { return val.value(); } template -STORAGE_TYPE rawValue(LLUnitImplicit val) { return val.value(); } +STORAGE_TYPE storageValue(LLUnitImplicit val) { return val.value(); } -#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name, unit_label) \ +#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ +struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }} + +#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \ struct unit_name \ { \ typedef base_unit_name base_unit_t; \ static const char* getUnitLabel() { return unit_label; } \ }; \ template \ -struct ConversionFactor \ +struct Convert \ { \ - static F64 get() \ + static STORAGE_TYPE get(STORAGE_TYPE val) \ { \ - return (F64)conversion_factor; \ + return (LinearOps(val) conversion_operation).mValue; \ } \ }; \ \ template \ -struct ConversionFactor \ +struct Convert \ { \ - static F64 get() \ + static STORAGE_TYPE get(STORAGE_TYPE val) \ { \ - return (F64)(1.0 / (conversion_factor)); \ + return (InverseLinearOps(val) conversion_operation).mValue; \ } \ } -#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ -struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }} - LL_DECLARE_BASE_UNIT(Bytes, "B"); -LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kibibytes, "KiB"); -LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Mibibytes, "MiB"); -LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gibibytes, "GiB"); -LL_DECLARE_DERIVED_UNIT(1.0 / 8.0, Bytes, Bits, "b"); -LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Kibibits, "Kib"); -LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Mibibits, "Mib"); -LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gibibits, "Gib"); +LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Bytes, * 1000 * 1000); +LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Bytes, * 1000 * 1000 * 1000); +LL_DECLARE_DERIVED_UNIT(Kibibytes, "KiB", Bytes, * 1024); +LL_DECLARE_DERIVED_UNIT(Mibibytes, "MiB", Bytes, * 1024 * 1024); +LL_DECLARE_DERIVED_UNIT(Gibibytes, "GiB", Bytes, * 1024 * 1024 * 1024); + +LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, / 8); +LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bytes, * (1000 / 8)); +LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Bytes, * (1000 / 8)); +LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Bytes, * (1000 * 1000 * 1000 / 8)); +LL_DECLARE_DERIVED_UNIT(Kibibits, "Kib", Bytes, * (1024 / 8)); +LL_DECLARE_DERIVED_UNIT(Mibibits, "Mib", Bytes, * (1024 / 8)); +LL_DECLARE_DERIVED_UNIT(Gibibits, "Gib", Bytes, * (1024 * 1024 * 1024 / 8)); LL_DECLARE_BASE_UNIT(Seconds, "s"); -LL_DECLARE_DERIVED_UNIT(60, Seconds, Minutes, "min"); -LL_DECLARE_DERIVED_UNIT(60 * 60, Seconds, Hours, "h"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Seconds, Milliseconds, "ms"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000000.0, Seconds, Microseconds, "\x09\x3cs"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000000000.0, Seconds, Nanoseconds, "ns"); +LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, * 60); +LL_DECLARE_DERIVED_UNIT(Hours, "h", Seconds, * 60 * 60); +LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, / 1000); +LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Seconds, / 1000000); +LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Seconds, / 1000000000); LL_DECLARE_BASE_UNIT(Meters, "m"); -LL_DECLARE_DERIVED_UNIT(1000, Meters, Kilometers, "km"); -LL_DECLARE_DERIVED_UNIT(1.0 / 100.0, Meters, Centimeters, "cm"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Meters, Millimeters, "mm"); +LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, * 1000); +LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100); +LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, * 1000); LL_DECLARE_BASE_UNIT(Hertz, "Hz"); -LL_DECLARE_DERIVED_UNIT(1000, Hertz, Kilohertz, "KHz"); -LL_DECLARE_DERIVED_UNIT(1000 * 1000, Hertz, Megahertz, "MHz"); -LL_DECLARE_DERIVED_UNIT(1000 * 1000 * 1000, Hertz, Gigahertz, "GHz"); +LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, * 1000); +LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Hertz, * 1000 * 1000); +LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Hertz, * 1000 * 1000 * 1000); LL_DECLARE_BASE_UNIT(Radians, "rad"); -LL_DECLARE_DERIVED_UNIT(0.01745329251994, Radians, Degrees, "deg"); +LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 0.01745329251994); } // namespace LLUnits diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp index 33e30f9688..747e8d1827 100644 --- a/indra/llcommon/tests/llunits_test.cpp +++ b/indra/llcommon/tests/llunits_test.cpp @@ -34,8 +34,8 @@ namespace LLUnits { // using powers of 2 to allow strict floating point equality LL_DECLARE_BASE_UNIT(Quatloos, "Quat"); - LL_DECLARE_DERIVED_UNIT(4, Quatloos, Latinum, "Lat"); - LL_DECLARE_DERIVED_UNIT((1.0 / 4.0), Quatloos, Solari, "Sol"); + LL_DECLARE_DERIVED_UNIT(Latinum, "Lat", Quatloos, * 4); + LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Quatloos, / 4); } namespace tut @@ -53,105 +53,107 @@ namespace tut template<> template<> void units_object_t::test<1>() { - LLUnit float_quatloos; - ensure(float_quatloos.value() == 0.f); + LLUnit float_quatloos; + ensure(float_quatloos == 0.f); - LLUnit int_quatloos; - ensure(int_quatloos.value() == 0); + LLUnit int_quatloos; + ensure(int_quatloos == 0); int_quatloos = 42; - ensure(int_quatloos.value() == 42); + ensure(int_quatloos == 42); float_quatloos = int_quatloos; - ensure(float_quatloos.value() == 42.f); + ensure(float_quatloos == 42.f); int_quatloos = float_quatloos; - ensure(int_quatloos.value() == 42); + ensure(int_quatloos == 42); float_quatloos = 42.1f; - ensure(float_quatloos.value() == 42.1f); + ensure(float_quatloos == 42.1f); int_quatloos = float_quatloos; - ensure(int_quatloos.value() == 42); - LLUnit unsigned_int_quatloos(float_quatloos); - ensure(unsigned_int_quatloos.value() == 42); + ensure(int_quatloos == 42); + LLUnit unsigned_int_quatloos(float_quatloos); + ensure(unsigned_int_quatloos == 42); } // conversions to/from base unit template<> template<> void units_object_t::test<2>() { - LLUnit quatloos(1.f); - ensure(quatloos.value() == 1.f); - LLUnit latinum_bars(quatloos); - ensure(latinum_bars.value() == 1.f / 4.f); + LLUnit quatloos(1.f); + ensure(quatloos == 1.f); + LLUnit latinum_bars(quatloos); + ensure(latinum_bars == 1.f / 4.f); latinum_bars = 256; quatloos = latinum_bars; - ensure(quatloos.value() == 1024); + ensure(quatloos == 1024); - LLUnit solari(quatloos); - ensure(solari.value() == 4096); + LLUnit solari(quatloos); + ensure(solari == 4096); } // conversions across non-base units template<> template<> void units_object_t::test<3>() { - LLUnit solari = 4.f; - LLUnit latinum_bars = solari; - ensure(latinum_bars.value() == 0.25f); + LLUnit solari = 4.f; + LLUnit latinum_bars = solari; + ensure(latinum_bars == 0.25f); } // math operations template<> template<> void units_object_t::test<4>() { - LLUnit quatloos = 1.f; + LLUnit quatloos = 1.f; quatloos *= 4.f; - ensure(quatloos.value() == 4); + ensure(quatloos == 4); quatloos = quatloos * 2; - ensure(quatloos.value() == 8); + ensure(quatloos == 8); quatloos = 2.f * quatloos; - ensure(quatloos.value() == 16); + ensure(quatloos == 16); quatloos += 4.f; - ensure(quatloos.value() == 20); + ensure(quatloos == 20); quatloos += 4; - ensure(quatloos.value() == 24); + ensure(quatloos == 24); quatloos = quatloos + 4; - ensure(quatloos.value() == 28); + ensure(quatloos == 28); quatloos = 4 + quatloos; - ensure(quatloos.value() == 32); + ensure(quatloos == 32); quatloos += quatloos * 3; - ensure(quatloos.value() == 128); + ensure(quatloos == 128); quatloos -= quatloos / 4 * 3; - ensure(quatloos.value() == 32); + ensure(quatloos == 32); quatloos = quatloos - 8; - ensure(quatloos.value() == 24); + ensure(quatloos == 24); quatloos -= 4; - ensure(quatloos.value() == 20); + ensure(quatloos == 20); quatloos -= 4.f; - ensure(quatloos.value() == 16); + ensure(quatloos == 16); quatloos *= 2.f; - ensure(quatloos.value() == 32); + ensure(quatloos == 32); quatloos = quatloos * 2.f; - ensure(quatloos.value() == 64); + ensure(quatloos == 64); quatloos = 0.5f * quatloos; - ensure(quatloos.value() == 32); + ensure(quatloos == 32); quatloos /= 2.f; - ensure(quatloos.value() == 16); + ensure(quatloos == 16); quatloos = quatloos / 4; - ensure(quatloos.value() == 4); + ensure(quatloos == 4); - F32 ratio = quatloos / LLUnit(4.f); + F32 ratio = quatloos / LLUnit(4.f); + ensure(ratio == 1); + ratio = quatloos / LLUnit(16.f); ensure(ratio == 1); - quatloos += LLUnit(4.f); - ensure(quatloos.value() == 5); - quatloos -= LLUnit(1.f); - ensure(quatloos.value() == 1); + quatloos += LLUnit(4.f); + ensure(quatloos == 5); + quatloos -= LLUnit(1.f); + ensure(quatloos == 1); } // implicit units @@ -159,16 +161,16 @@ namespace tut void units_object_t::test<5>() { // 0-initialized - LLUnit quatloos(0); + LLUnit quatloos(0); // initialize implicit unit from explicit - LLUnitImplicit quatloos_implicit = quatloos + 1; - ensure(quatloos_implicit.value() == 1); + LLUnitImplicit quatloos_implicit = quatloos + 1; + ensure(quatloos_implicit == 1); // assign implicit to explicit, or perform math operations quatloos = quatloos_implicit; - ensure(quatloos.value() == 1); + ensure(quatloos == 1); quatloos += quatloos_implicit; - ensure(quatloos.value() == 2); + ensure(quatloos == 2); // math operations on implicits quatloos_implicit = 1; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 2c3fcfcec1..cb99a651c6 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -51,9 +51,9 @@ U32 wpo2(U32 i); U32 LLImageGL::sUniqueCount = 0; U32 LLImageGL::sBindCount = 0; -LLUnit LLImageGL::sGlobalTextureMemory = 0; -LLUnit LLImageGL::sBoundTextureMemory = 0; -LLUnit LLImageGL::sCurBoundTextureMemory = 0; +LLUnit LLImageGL::sGlobalTextureMemory = 0; +LLUnit LLImageGL::sBoundTextureMemory = 0; +LLUnit LLImageGL::sCurBoundTextureMemory = 0; S32 LLImageGL::sCount = 0; LLImageGL::dead_texturelist_t LLImageGL::sDeadTextureList[LLTexUnit::TT_NONE]; U32 LLImageGL::sCurTexName = 1; diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 2b568e5e0f..227ccc90bd 100755 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -246,9 +246,9 @@ public: static F32 sLastFrameTime; // Global memory statistics - static LLUnit sGlobalTextureMemory; // Tracks main memory texmem - static LLUnit sBoundTextureMemory; // Tracks bound texmem for last completed frame - static LLUnit sCurBoundTextureMemory; // Tracks bound texmem for current frame + static LLUnit sGlobalTextureMemory; // Tracks main memory texmem + static LLUnit sBoundTextureMemory; // Tracks bound texmem for last completed frame + static LLUnit sCurBoundTextureMemory; // Tracks bound texmem for current frame static U32 sBindCount; // Tracks number of texture binds for current frame static U32 sUniqueCount; // Tracks number of unique texture binds for current frame static BOOL sGlobalUseAnisotropic; diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp index 6966df8213..d3cc2733e6 100755 --- a/indra/llui/llstatbar.cpp +++ b/indra/llui/llstatbar.cpp @@ -284,7 +284,7 @@ void LLStatBar::draw() // draw background bar. gl_rect_2d(bar_left, bar_top, bar_right, bar_bottom, LLColor4(0.f, 0.f, 0.f, 0.25f)); - if (frame_recording.getNumPeriods() == 0) + if (frame_recording.getNumRecordedPeriods() == 0) { // No data, don't draw anything... return; @@ -315,7 +315,7 @@ void LLStatBar::draw() if (mDisplayHistory && (mCountFloatp || mEventFloatp || mSampleFloatp)) { - const S32 num_values = frame_recording.getNumPeriods() - 1; + const S32 num_values = frame_recording.getNumRecordedPeriods() - 1; F32 begin = 0; F32 end = 0; S32 i; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 42bf9b657b..ef24ba21ee 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -296,7 +296,7 @@ LLPumpIO* gServicePump = NULL; U64 gFrameTime = 0; F32 gFrameTimeSeconds = 0.f; -LLUnit gFrameIntervalSeconds = 0.f; +LLUnit gFrameIntervalSeconds = 0.f; F32 gFPSClamped = 10.f; // Pretend we start at target rate. F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 2e75de445f..ad662d8ea1 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -337,7 +337,7 @@ extern LLPumpIO* gServicePump; extern U64 gFrameTime; // The timestamp of the most-recently-processed frame extern F32 gFrameTimeSeconds; // Loses msec precision after ~4.5 hours... -extern LLUnit gFrameIntervalSeconds; // Elapsed time between current and previous gFrameTimeSeconds +extern LLUnit gFrameIntervalSeconds; // Elapsed time between current and previous gFrameTimeSeconds extern F32 gFPSClamped; // Frames per second, smoothed, weighted toward last frame extern F32 gFrameDTClamped; extern U64 gStartTime; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 40526d3357..8e061ec87c 100755 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -101,21 +101,15 @@ LLFastTimerView::LLFastTimerView(const LLSD& key) mScrollIndex(0), mHoverID(NULL), mHoverBarIndex(-1), - mPrintStats(-1), - mRecording(&get_frame_recording()), - mPauseHistory(false) + mStatsIndex(-1), + mPauseHistory(false), + mRecording(512) { - mTimerBars = new std::vector[MAX_VISIBLE_HISTORY + 1]; + mTimerBarRows.resize(MAX_VISIBLE_HISTORY); } LLFastTimerView::~LLFastTimerView() { - if (mRecording != &get_frame_recording()) - { - delete mRecording; - } - mRecording = NULL; - delete [] mTimerBars; } void LLFastTimerView::onPause() @@ -130,16 +124,11 @@ void LLFastTimerView::setPauseState(bool pause_state) // reset scroll to bottom when unpausing if (!pause_state) { - if (mRecording != &get_frame_recording()) - { - delete mRecording; - } - mRecording = &get_frame_recording(); + getChild("pause_btn")->setLabel(getString("pause")); } else { - mRecording = new PeriodicRecording(get_frame_recording()); mScrollIndex = 0; getChild("pause_btn")->setLabel(getString("run")); @@ -175,7 +164,7 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) { S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight()); bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY); - mPrintStats = mScrollIndex + bar_idx; + mStatsIndex = mScrollIndex + bar_idx; return TRUE; } return LLFloater::handleRightMouseDown(x, y, mask); @@ -262,8 +251,8 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) if (hasMouseCapture()) { F32 lerp = llclamp(1.f - (F32) (x - mGraphRect.mLeft) / (F32) mGraphRect.getWidth(), 0.f, 1.f); - mScrollIndex = llround( lerp * (F32)(mRecording->getNumPeriods() - MAX_VISIBLE_HISTORY)); - mScrollIndex = llclamp( mScrollIndex, 0, (S32)mRecording->getNumPeriods()); + mScrollIndex = llround( lerp * (F32)(mRecording.getNumRecordedPeriods() - MAX_VISIBLE_HISTORY)); + mScrollIndex = llclamp( mScrollIndex, 0, (S32)mRecording.getNumRecordedPeriods()); return TRUE; } mHoverTimer = NULL; @@ -272,7 +261,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) if(mPauseHistory && mBarRect.pointInRect(x, y)) { mHoverBarIndex = llmin((mBarRect.mTop - y) / (mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2)) - 1, - (S32)mRecording->getNumPeriods() - 1, + (S32)mRecording.getNumRecordedPeriods() - 1, MAX_VISIBLE_HISTORY); if (mHoverBarIndex == 0) { @@ -289,7 +278,8 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) ++it, ++i) { // is mouse over bar for this timer? - if (mTimerBars[mHoverBarIndex][i].mVisibleRect.pointInRect(x, y)) + TimerBarRow& row = mHoverBarIndex == 0 ? mAverageTimerRow : mTimerBarRows[mHoverBarIndex - 1]; + if (row.mBars[i].mVisibleRect.pointInRect(x, y - row.mBottom)) { mHoverID = (*it); if (mHoverTimer != *it) @@ -301,7 +291,8 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) mHoverTimer = (*it); } - mToolTipRect = mTimerBars[mHoverBarIndex][i].mVisibleRect; + mToolTipRect = row.mBars[i].mVisibleRect; + mToolTipRect.translate(0, row.mBottom); } if ((*it)->getCollapsed()) @@ -329,11 +320,11 @@ static std::string get_tooltip(TimeBlock& timer, S32 history_index, PeriodicReco if (history_index == 0) { // by default, show average number of call - tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit(frame_recording.getPeriodMean(timer)).value(), (S32)frame_recording.getPeriodMean(timer.callCount())); + tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit(frame_recording.getPeriodMean(timer)).value(), (S32)frame_recording.getPeriodMean(timer.callCount())); } else { - tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit(frame_recording.getPrevRecording(history_index).getSum(timer)).value(), (S32)frame_recording.getPrevRecording(history_index).getSum(timer.callCount())); + tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit(frame_recording.getPrevRecording(history_index).getSum(timer)).value(), (S32)frame_recording.getPrevRecording(history_index).getSum(timer.callCount())); } return tooltip; } @@ -348,7 +339,7 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) LLRect screen_rect; localRectToScreen(mToolTipRect, &screen_rect); - std::string tooltip = get_tooltip(*mHoverTimer, mHoverBarIndex > 0 ? mScrollIndex + mHoverBarIndex : 0, *mRecording); + std::string tooltip = get_tooltip(*mHoverTimer, mHoverBarIndex > 0 ? mScrollIndex + mHoverBarIndex : 0, mRecording); LLToolTipMgr::instance().show(LLToolTip::Params() .message(tooltip) @@ -366,7 +357,7 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) TimeBlock* idp = getLegendID(y); if (idp) { - LLToolTipMgr::instance().show(get_tooltip(*idp, 0, *mRecording)); + LLToolTipMgr::instance().show(get_tooltip(*idp, 0, mRecording)); return TRUE; } @@ -381,7 +372,7 @@ BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks) setPauseState(true); mScrollIndex = llclamp( mScrollIndex + clicks, 0, - llmin((S32)mRecording->getNumPeriods(), (S32)mRecording->getNumPeriods() - MAX_VISIBLE_HISTORY)); + llmin((S32)mRecording.getNumRecordedPeriods(), (S32)mRecording.getNumRecordedPeriods() - MAX_VISIBLE_HISTORY)); return TRUE; } @@ -389,12 +380,19 @@ static TimeBlock FTM_RENDER_TIMER("Timers", true); static const S32 MARGIN = 10; static const S32 LEGEND_WIDTH = 220; -static std::map sTimerColors; +static std::vector sTimerColors; void LLFastTimerView::draw() { LLFastTimer t(FTM_RENDER_TIMER); + if (!mPauseHistory) + { + mRecording.appendRecording(LLTrace::get_frame_recording().getLastRecording()); + mTimerBarRows.pop_back(); + mTimerBarRows.push_front(TimerBarRow()); + } + generateUniqueColors(); // Draw the window background @@ -417,11 +415,20 @@ void LLFastTimerView::draw() printLineStats(); LLView::draw(); - mAllTimeMax = llmax(mAllTimeMax, mRecording->getLastRecording().getSum(FTM_FRAME)); + mAllTimeMax = llmax(mAllTimeMax, mRecording.getLastRecording().getSum(FTM_FRAME)); mHoverID = NULL; mHoverBarIndex = -1; } +void LLFastTimerView::onOpen(const LLSD& key) +{ + if (mRecording.getNumRecordedPeriods() == 0) + { + mRecording.appendPeriodicRecording(LLTrace::get_frame_recording()); + } +} + + void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch) { //read result back into raw image @@ -828,7 +835,7 @@ void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target LLSD current = analyzePerformanceLogDefault(target_is); target_is.close(); - //output comparision + //output comparison std::ofstream os(output.c_str()); LLSD::Real session_time = current["SessionTime"].asReal(); @@ -936,7 +943,7 @@ void LLFastTimerView::onClickCloseBtn() void LLFastTimerView::printLineStats() { // Output stats for clicked bar to log - if (mPrintStats >= 0) + if (mStatsIndex >= 0) { std::string legend_stat; bool first = true; @@ -974,16 +981,16 @@ void LLFastTimerView::printLineStats() } first = false; - LLUnit ticks; - if (mPrintStats > 0) + LLUnit ticks; + if (mStatsIndex == 0) { - ticks = mRecording->getPrevRecording(mPrintStats).getSum(*idp); + ticks = mRecording.getPeriodMean(*idp); } else { - ticks = mRecording->getPeriodMean(*idp); + ticks = mRecording.getPrevRecording(mStatsIndex).getSum(*idp); } - LLUnit ms = ticks; + LLUnit ms = ticks; timer_stat += llformat("%.1f",ms.value()); @@ -993,7 +1000,7 @@ void LLFastTimerView::printLineStats() } } llinfos << timer_stat << llendl; - mPrintStats = -1; + mStatsIndex = -1; } } @@ -1009,7 +1016,7 @@ void LLFastTimerView::drawLineGraph() LLLocalClipRect clip(mGraphRect); //normalize based on last frame's maximum - static LLUnit max_time = 0.000001; + static LLUnit max_time = 0.000001; static U32 max_calls = 0; static F32 alpha_interp = 0.f; @@ -1020,7 +1027,7 @@ void LLFastTimerView::drawLineGraph() else if (mDisplayHz) axis_label = llformat("%d Hz", (int)(1.f / max_time.value())); else - axis_label = llformat("%4.2f ms", LLUnit(max_time).value()); + axis_label = llformat("%4.2f ms", LLUnit(max_time).value()); x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(axis_label)-5; y = mGraphRect.mTop - LLFontGL::getFontMonospace()->getLineHeight(); @@ -1030,10 +1037,10 @@ void LLFastTimerView::drawLineGraph() //highlight visible range { - S32 first_frame = mRecording->getNumPeriods() - mScrollIndex; + S32 first_frame = mRecording.getNumRecordedPeriods() - mScrollIndex; S32 last_frame = first_frame - MAX_VISIBLE_HISTORY; - F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(mRecording->getNumPeriods()-1); + F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(mRecording.getNumRecordedPeriods()-1); F32 right = (F32) mGraphRect.mLeft + frame_delta*first_frame; F32 left = (F32) mGraphRect.mLeft + frame_delta*last_frame; @@ -1055,7 +1062,7 @@ void LLFastTimerView::drawLineGraph() } } - LLUnit cur_max = 0; + LLUnit cur_max = 0; U32 cur_max_calls = 0; for(timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); it != end_timer_tree(); @@ -1070,7 +1077,7 @@ void LLFastTimerView::drawLineGraph() glLineWidth(3); } - const F32 * col = sTimerColors[idp].mV;// ft_display_table[idx].color->mV; + const F32 * col = sTimerColors[idp->getIndex()].mV;// ft_display_table[idx].color->mV; F32 alpha = 1.f; @@ -1085,12 +1092,13 @@ void LLFastTimerView::drawLineGraph() gGL.color4f(col[0], col[1], col[2], alpha); gGL.begin(LLRender::TRIANGLE_STRIP); - for (U32 j = mRecording->getNumPeriods(); + for (U32 j = mRecording.getNumRecordedPeriods(); j > 0; j--) { - LLUnit time = llmax(mRecording->getPrevRecording(j).getSum(*idp), LLUnit(0.000001)); - U32 calls = mRecording->getPrevRecording(j).getSum(idp->callCount()); + LLTrace::Recording& recording = mRecording.getPrevRecording(j); + LLUnit time = llmax(recording.getSum(*idp), LLUnit(0.000001)); + U32 calls = recording.getSum(idp->callCount()); if (alpha == 1.f) { @@ -1098,7 +1106,7 @@ void LLFastTimerView::drawLineGraph() cur_max = llmax(cur_max, time); cur_max_calls = llmax(cur_max_calls, calls); } - F32 x = mGraphRect.mRight - j * (F32)(mGraphRect.getWidth())/(mRecording->getNumPeriods()-1); + F32 x = mGraphRect.mRight - j * (F32)(mGraphRect.getWidth())/(mRecording.getNumRecordedPeriods()-1); F32 y = mDisplayHz ? mGraphRect.mBottom + (1.f / time.value()) * ((F32) mGraphRect.getHeight() / (1.f / max_time.value())) : mGraphRect.mBottom + time / max_time * (F32)mGraphRect.getHeight(); @@ -1124,7 +1132,7 @@ void LLFastTimerView::drawLineGraph() max_time = lerp(max_time.value(), cur_max.value(), LLSmoothInterpolation::getInterpolant(0.1f)); if (max_time - cur_max <= 1 || cur_max - max_time <= 1) { - max_time = llmax(LLUnit(1), LLUnit(cur_max)); + max_time = llmax(LLUnit(1), LLUnit(cur_max)); } max_calls = llround(lerp((F32)max_calls, (F32) cur_max_calls, LLSmoothInterpolation::getInterpolant(0.1f))); @@ -1183,20 +1191,20 @@ void LLFastTimerView::drawLegend( S32 y ) scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f); } bar_rect.stretch(scale_offset); - gl_rect_2d(bar_rect, sTimerColors[idp]); + gl_rect_2d(bar_rect, sTimerColors[idp->getIndex()]); - LLUnit ms = 0; + LLUnit ms = 0; S32 calls = 0; if (mHoverBarIndex > 0 && mHoverID) { S32 hidx = mScrollIndex + mHoverBarIndex; - ms = mRecording->getPrevRecording(hidx).getSum(*idp); - calls = mRecording->getPrevRecording(hidx).getSum(idp->callCount()); + ms = mRecording.getPrevRecording(hidx).getSum(*idp); + calls = mRecording.getPrevRecording(hidx).getSum(idp->callCount()); } else { - ms = LLUnit(mRecording->getPeriodMean(*idp)); - calls = (S32)mRecording->getPeriodMean(idp->callCount()); + ms = LLUnit(mRecording.getPeriodMean(*idp)); + calls = (S32)mRecording.getPeriodMean(idp->callCount()); } std::string timer_label; @@ -1254,7 +1262,8 @@ void LLFastTimerView::generateUniqueColors() { // generate unique colors { - sTimerColors[&FTM_FRAME] = LLColor4::grey; + sTimerColors.reserve(LLTrace::TimeBlock::getNumIndices()); + sTimerColors[FTM_FRAME.getIndex()] = LLColor4::grey; F32 hue = 0.f; @@ -1274,7 +1283,7 @@ void LLFastTimerView::generateUniqueColors() LLColor4 child_color; child_color.setHSL(hue, saturation, lightness); - sTimerColors[idp] = child_color; + sTimerColors[idp->getIndex()] = child_color; } } } @@ -1315,7 +1324,7 @@ void LLFastTimerView::drawTicks() { // Draw MS ticks { - LLUnit ms = mTotalTimeDisplay; + LLUnit ms = mTotalTimeDisplay; std::string tick_label; S32 x; S32 barw = mBarRect.getWidth(); @@ -1382,127 +1391,127 @@ void LLFastTimerView::updateTotalTime() switch(mDisplayMode) { case 0: - mTotalTimeDisplay = mRecording->getPeriodMean(FTM_FRAME)*2; + mTotalTimeDisplay = mRecording.getPeriodMean(FTM_FRAME)*2; break; case 1: mTotalTimeDisplay = mAllTimeMax; break; case 2: // Calculate the max total ticks for the current history - mTotalTimeDisplay = mRecording->getPeriodMax(FTM_FRAME); + mTotalTimeDisplay = mRecording.getPeriodMax(FTM_FRAME); break; default: - mTotalTimeDisplay = LLUnit(100); + mTotalTimeDisplay = LLUnit(100); break; } - mTotalTimeDisplay = LLUnit(llceil(mTotalTimeDisplay.as().value() / 20.f) * 20.f); + mTotalTimeDisplay = LLUnit(llceil(mTotalTimeDisplay.as().value() / 20.f) * 20.f); } void LLFastTimerView::drawBars() { - updateTotalTime(); - if (mTotalTimeDisplay <= 0.0) return; - LLLocalClipRect clip(mBarRect); S32 bar_height = mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2); - S32 vpad = llmax(1, bar_height / 4); // spacing between bars + const S32 vpad = llmax(1, bar_height / 4); // spacing between bars bar_height -= vpad; + updateTotalTime(); + if (mTotalTimeDisplay <= 0.0) return; + drawTicks(); - S32 y = mBarRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4); - drawBorders(y, mBarRect.mLeft, bar_height, vpad); + const S32 bars_top = mBarRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4); + drawBorders(bars_top, mBarRect.mLeft, bar_height, vpad); // Draw bars for each history entry - // Special: -1 = show running average + // Special: 0 = show running average LLPointer bar_image = LLUI::getUIImage("Rounded_Square"); + + const S32 image_width = bar_image->getTextureWidth(); + const S32 image_height = bar_image->getTextureHeight(); + gGL.getTexUnit(0)->bind(bar_image->getImage()); - const S32 histmax = llmin((S32)mRecording->getNumPeriods(), MAX_VISIBLE_HISTORY) + 1; + { + const S32 histmax = llmin((S32)mRecording.getNumRecordedPeriods(), MAX_VISIBLE_HISTORY); - for (S32 bar_index = 0; bar_index < histmax && y > LINE_GRAPH_HEIGHT; bar_index++) - { - S32 history_index = (bar_index > 0) - ? bar_index + mScrollIndex - : -1; - mTimerBars[bar_index].clear(); - mTimerBars[bar_index].reserve(LLInstanceTracker::instanceCount()); - - updateTimerBarWidths(&FTM_FRAME, mTimerBars[bar_index], history_index, true); - LLRect frame_bar_rect(mBarRect.mLeft, y, mBarRect.mLeft + mTimerBars[bar_index][0].mWidth, y-bar_height); - mTimerBars[bar_index][0].mVisibleRect = frame_bar_rect; - updateTimerBarFractions(&FTM_FRAME, 0, mTimerBars[bar_index]); - drawBar(&FTM_FRAME, frame_bar_rect, mTimerBars[bar_index], 0, bar_image); - - y -= (bar_height + vpad); - if (bar_index == 0) - y -= bar_height; - } + llassert(mTimerBarRows.size() >= histmax); + + // update widths + updateTimerBarWidths(&FTM_FRAME, mAverageTimerRow, -1); + mAverageTimerRow.mBars[0].mVisibleRect = LLRect(mBarRect.mLeft, 0, mBarRect.mLeft + mAverageTimerRow.mBars[0].mWidth, -bar_height); + updateTimerBarFractions(&FTM_FRAME, mAverageTimerRow); + + for (S32 history_index = 0; history_index < histmax; history_index++) + { + TimerBarRow& row = mTimerBarRows[history_index]; + if (row.mBars.empty()) + { + row.mBars.reserve(LLInstanceTracker::instanceCount()); + updateTimerBarWidths(&FTM_FRAME, row, history_index); + row.mBars[0].mVisibleRect = LLRect(mBarRect.mLeft, 0, mBarRect.mLeft + row.mBars[0].mWidth, -1); + updateTimerBarFractions(&FTM_FRAME, row); + } + } + + // draw bars + LLRect frame_bar_rect( mBarRect.mLeft, + bars_top, + mBarRect.mLeft + mAverageTimerRow.mBars[0].mWidth, + bars_top - bar_height); + mAverageTimerRow.mBottom = frame_bar_rect.mBottom; + drawBar(&FTM_FRAME, frame_bar_rect, mAverageTimerRow, image_width, image_height, false); + frame_bar_rect.translate(0, -(bar_height + vpad + bar_height)); + + for(S32 bar_index = mScrollIndex; bar_index < llmin(histmax, mScrollIndex + MAX_VISIBLE_HISTORY); ++bar_index) + { + TimerBarRow& row = mTimerBarRows[bar_index]; + row.mBottom = frame_bar_rect.mBottom; + drawBar(&FTM_FRAME, frame_bar_rect, row, image_width, image_height, false); + + frame_bar_rect.translate(0, -(bar_height + vpad)); + } + + } gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_WIDTHS("Update timer bar widths"); -S32 LLFastTimerView::updateTimerBarWidths(LLTrace::TimeBlock* time_block, std::vector& bars, S32 history_index, bool visible) +S32 LLFastTimerView::updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, bool visible) { + std::vector& bars = row.mBars; LLFastTimer _(FTM_UPDATE_TIMER_BAR_WIDTHS); - F32 self_time_frame_fraction = history_index == -1 - ? (mRecording->getPeriodMean(time_block->selfTime()) / mTotalTimeDisplay) - : (mRecording->getPrevRecording(history_index).getSum(time_block->selfTime()) / mTotalTimeDisplay); + const F32 self_time_frame_fraction = history_index == -1 + ? (mRecording.getPeriodMean(time_block->selfTime()) / mTotalTimeDisplay) + : (mRecording.getPrevRecording(history_index).getSum(time_block->selfTime()) / mTotalTimeDisplay); - S32 self_time_width = llround(self_time_frame_fraction * (F32)mBarRect.getWidth()); + const S32 self_time_width = llround(self_time_frame_fraction * (F32)mBarRect.getWidth()); S32 full_width = self_time_width; - bool children_visible = visible; - // reserve a spot for this bar to be rendered before its children // even though we don't know its size yet - S32 bar_rect_index = bars.size(); - if (visible) - { - bars.push_back(TimerBar()); - } + bars.push_back(TimerBar()); + TimerBar& timer_bar = bars.back(); - if (time_block->getCollapsed()) - { - children_visible = false; - } + const bool children_visible = visible && !time_block->getCollapsed(); for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); it != end_it; ++it) { - full_width += updateTimerBarWidths(*it, bars, history_index, children_visible); + full_width += updateTimerBarWidths(*it, row, history_index, children_visible); } - if (visible) - { - TimerBar& timer_bar = bars[bar_rect_index]; - - timer_bar.mWidth = full_width; - timer_bar.mSelfWidth = self_time_width; - timer_bar.mColor = sTimerColors[time_block]; - - BOOL is_child_of_hover_item = (time_block == mHoverID); - TimeBlock* next_parent = time_block->getParent(); - while(!is_child_of_hover_item && next_parent) - { - is_child_of_hover_item = (mHoverID == next_parent); - if (next_parent->getParent() == next_parent) break; - next_parent = next_parent->getParent(); - } - - if (mHoverID != NULL - && time_block != mHoverID - && !is_child_of_hover_item) - { - timer_bar.mColor = lerp(timer_bar.mColor, LLColor4::grey, 0.8f); - } - } + timer_bar.mWidth = full_width; + timer_bar.mSelfWidth = self_time_width; + timer_bar.mTimeBlock = time_block; + timer_bar.mVisible = visible; + return full_width; } static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_FRACTIONS("Update timer bar fractions"); -S32 LLFastTimerView::updateTimerBarFractions(LLTrace::TimeBlock* time_block, S32 timer_bar_index, std::vector& bars) +S32 LLFastTimerView::updateTimerBarFractions(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 timer_bar_index) { + std::vector& bars = row.mBars; LLFastTimer _(FTM_UPDATE_TIMER_BAR_FRACTIONS); TimerBar& timer_bar = bars[timer_bar_index]; S32 child_time_width = timer_bar.mWidth - timer_bar.mSelfWidth; @@ -1518,11 +1527,6 @@ S32 LLFastTimerView::updateTimerBarFractions(LLTrace::TimeBlock* time_block, S32 } children_rect.mRight = children_rect.mLeft + timer_bar.mWidth - timer_bar.mSelfWidth; - if (children_rect.getHeight() > MIN_BAR_HEIGHT) - { - children_rect.mTop -= 1; - children_rect.mBottom += 1; - } timer_bar.mChildrenRect = children_rect; //now loop through children and figure out portion of bar image covered by each bar, now that we know the @@ -1548,7 +1552,7 @@ S32 LLFastTimerView::updateTimerBarFractions(LLTrace::TimeBlock* time_block, S32 children_rect.mLeft + llround(child_timer_bar.mEndFraction * children_rect.getWidth()), children_rect.mBottom); - timer_bar_index = updateTimerBarFractions(child_time_block, timer_bar_index, bars); + timer_bar_index = updateTimerBarFractions(child_time_block, row, timer_bar_index); bar_fraction_start = child_timer_bar.mEndFraction; } @@ -1556,25 +1560,29 @@ S32 LLFastTimerView::updateTimerBarFractions(LLTrace::TimeBlock* time_block, S32 return timer_bar_index; } -S32 LLFastTimerView::drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, std::vector& bars, S32 bar_index, LLPointer& bar_image) +S32 LLFastTimerView::drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, S32 bar_index) { - TimerBar& timer_bar = bars[bar_index]; + TimerBar& timer_bar = row.mBars[bar_index]; + + hovered |= mHoverID == time_block; // animate scale of bar when hovering over that particular timer if (bar_rect.getWidth() > 0) { LLRect render_rect(bar_rect); S32 scale_offset = 0; - if (time_block == mHoverID) + if (mHoverID == time_block) { scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 3.f); render_rect.mTop += scale_offset; render_rect.mBottom -= scale_offset; } - gGL.color4fv(timer_bar.mColor.mV); + LLColor4 color = sTimerColors[time_block->getIndex()]; + if (!hovered) color = lerp(color, LLColor4::grey, 0.8f); + gGL.color4fv(color.mV); gl_segmented_rect_2d_fragment_tex(render_rect, - bar_image->getTextureWidth(), bar_image->getTextureHeight(), + image_width, image_height, 16, timer_bar.mStartFraction, timer_bar.mEndFraction); } @@ -1584,7 +1592,20 @@ S32 LLFastTimerView::drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, st for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); it != end_it; ++it) { ++bar_index; - bar_index = drawBar(*it, timer_bar.mChildrenRect, bars, bar_index, bar_image); + LLRect children_rect = timer_bar.mChildrenRect; + children_rect.translate(0, row.mBottom); + if (bar_rect.getHeight() > MIN_BAR_HEIGHT) + { + // shrink as we go down a level + children_rect.mTop = bar_rect.mTop - 1; + children_rect.mBottom = bar_rect.mBottom + 1; + } + else + { + children_rect.mTop = bar_rect.mTop; + children_rect.mBottom = bar_rect.mBottom; + } + bar_index = drawBar(*it, children_rect, row, image_width, image_height, hovered, bar_index); } } diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 341adacd65..c20cadd6d7 100755 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -31,6 +31,7 @@ #include "llfasttimer.h" #include "llunit.h" #include "lltracerecording.h" +#include class LLFastTimerView : public LLFloater { @@ -60,13 +61,11 @@ public: virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual void draw(); - + virtual void onOpen(const LLSD& key); LLTrace::TimeBlock* getLegendID(S32 y); -protected: - virtual void onClickCloseBtn(); - private: + virtual void onClickCloseBtn(); void drawTicks(); void drawLineGraph(); void drawLegend(S32 y); @@ -87,47 +86,53 @@ private: mStartFraction(0.f), mEndFraction(1.f) {} - S32 mWidth; - S32 mSelfWidth; - LLRect mVisibleRect, - mChildrenRect; - LLColor4 mColor; - bool mVisible; - F32 mStartFraction, - mEndFraction; + S32 mWidth; + S32 mSelfWidth; + LLRect mVisibleRect, + mChildrenRect; + LLTrace::TimeBlock* mTimeBlock; + bool mVisible; + F32 mStartFraction, + mEndFraction; }; - S32 updateTimerBarWidths(LLTrace::TimeBlock* time_block, std::vector& bars, S32 history_index, bool visible); - S32 updateTimerBarFractions(LLTrace::TimeBlock* time_block, S32 timer_bar_index, std::vector& bars); - S32 drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, std::vector& bars, S32 bar_index, LLPointer& bar_image); + + struct TimerBarRow + { + S32 mBottom; + std::vector mBars; + }; + + S32 updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, bool visible = true); + S32 updateTimerBarFractions(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 timer_bar_index = 0); + S32 drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, S32 bar_index = 0); void setPauseState(bool pause_state); - std::vector* mTimerBars; - S32 mDisplayMode; + std::deque mTimerBarRows; + TimerBarRow mAverageTimerRow; - typedef enum child_alignment + enum ChildAlignment { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_COUNT - } ChildAlignment; - - ChildAlignment mDisplayCenter; - bool mDisplayCalls, - mDisplayHz; - LLUnit mAllTimeMax, - mTotalTimeDisplay; - LLRect mBarRect; - S32 mScrollIndex; - LLTrace::TimeBlock* mHoverID; - LLTrace::TimeBlock* mHoverTimer; - LLRect mToolTipRect; - S32 mHoverBarIndex; - LLFrameTimer mHighlightTimer; - S32 mPrintStats; - LLRect mGraphRect; - LLTrace::PeriodicRecording* mRecording; - bool mPauseHistory; + } mDisplayCenter; + bool mDisplayCalls, + mDisplayHz, + mPauseHistory; + LLUnit mAllTimeMax, + mTotalTimeDisplay; + S32 mScrollIndex, + mHoverBarIndex, + mStatsIndex; + S32 mDisplayMode; + LLTrace::TimeBlock* mHoverID; + LLTrace::TimeBlock* mHoverTimer; + LLRect mToolTipRect, + mGraphRect, + mBarRect; + LLFrameTimer mHighlightTimer; + LLTrace::PeriodicRecording mRecording; }; #endif diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index dccf8a2a17..3d9e0ab4c3 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -503,9 +503,9 @@ void LLSceneMonitor::dumpToFile(std::string file_name) os << std::setprecision(3); PeriodicRecording& scene_load_recording = mSceneLoadRecording.getAcceptedRecording(); - const U32 frame_count = scene_load_recording.getNumPeriods(); + const U32 frame_count = scene_load_recording.getNumRecordedPeriods(); - LLUnit frame_time; + LLUnit frame_time; os << "Stat"; for (S32 frame = 0; frame < frame_count; frame++) diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 2530beb722..7fc58e230c 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -330,7 +330,7 @@ private: LLTextureInfo mTextureInfo; // XXX possible delete - LLUnit mHTTPTextureBits; // Mfnq + LLUnit mHTTPTextureBits; // Mfnq // XXX possible delete //debug use diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index c9ec5d9bf6..766b66efa0 100755 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -507,17 +507,17 @@ private: void LLGLTexMemBar::draw() { - LLUnit bound_mem = LLViewerTexture::sBoundTextureMemory; - LLUnit max_bound_mem = LLViewerTexture::sMaxBoundTextureMem; - LLUnit total_mem = LLViewerTexture::sTotalTextureMemory; - LLUnit max_total_mem = LLViewerTexture::sMaxTotalTextureMem; + LLUnit bound_mem = LLViewerTexture::sBoundTextureMemory; + LLUnit max_bound_mem = LLViewerTexture::sMaxBoundTextureMem; + LLUnit total_mem = LLViewerTexture::sTotalTextureMemory; + LLUnit max_total_mem = LLViewerTexture::sMaxTotalTextureMem; F32 discard_bias = LLViewerTexture::sDesiredDiscardBias; F32 cache_usage = (F32)LLTrace::Mibibytes(LLAppViewer::getTextureCache()->getUsage()).value() ; F32 cache_max_usage = (F32)LLTrace::Mibibytes(LLAppViewer::getTextureCache()->getMaxUsage()).value() ; S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); - LLUnit total_texture_downloaded = gTotalTextureData; - LLUnit total_object_downloaded = gTotalObjectData; + LLUnit total_texture_downloaded = gTotalTextureData; + LLUnit total_object_downloaded = gTotalObjectData; U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ; U32 total_active_cached_objects = LLWorld::getInstance()->getNumOfActiveCachedObjects(); U32 total_objects = gObjectList.getNumObjects(); diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index 3a6ee636d4..dc4c9fe4ad 100755 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -486,10 +486,10 @@ void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output) grid_from_region_handle(it->first, &grid_x, &grid_y); r.grid_x(grid_x); r.grid_y(grid_y); - r.duration(LLUnit(rec.getDuration()).value()); + r.duration(LLUnit(rec.getDuration()).value()); } - stats.duration(mCurRecording ? LLUnit(mCurRecording->getDuration()).value() : 0.0); + stats.duration(mCurRecording ? LLUnit(mCurRecording->getDuration()).value() : 0.0); } LLSD LLViewerAssetStats::asLLSD(bool compact_output) diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index 1a8770f8a7..e03b7c53a6 100755 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -83,7 +83,7 @@ public: * for compatibility with the pre-existing timestamp on the texture * fetcher class, LLTextureFetch. */ - typedef LLUnit duration_t; + typedef LLUnit duration_t; /** * Type for the region identifier used in stats. Currently uses diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index f2a3ffc3dc..0309acdad2 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -4480,18 +4480,18 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) // *TODO: Remove this dependency, or figure out a better way to handle // this hack. -extern LLUnit gObjectData; +extern LLUnit gObjectData; void process_object_update(LLMessageSystem *mesgsys, void **user_data) { // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectData += (LLUnit)mesgsys->getReceiveCompressedSize(); + gObjectData += (LLUnit)mesgsys->getReceiveCompressedSize(); } else { - gObjectData += (LLUnit)mesgsys->getReceiveSize(); + gObjectData += (LLUnit)mesgsys->getReceiveSize(); } // Update the object... @@ -4503,11 +4503,11 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectData += (LLUnit)mesgsys->getReceiveCompressedSize(); + gObjectData += (LLUnit)mesgsys->getReceiveCompressedSize(); } else { - gObjectData += (LLUnit)mesgsys->getReceiveSize(); + gObjectData += (LLUnit)mesgsys->getReceiveSize(); } // Update the object... @@ -4519,11 +4519,11 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectData += (LLUnit)mesgsys->getReceiveCompressedSize(); + gObjectData += (LLUnit)mesgsys->getReceiveCompressedSize(); } else { - gObjectData += (LLUnit)mesgsys->getReceiveSize(); + gObjectData += (LLUnit)mesgsys->getReceiveSize(); } // Update the object... @@ -4535,11 +4535,11 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_ { if (mesgsys->getReceiveCompressedSize()) { - gObjectData += (LLUnit)mesgsys->getReceiveCompressedSize(); + gObjectData += (LLUnit)mesgsys->getReceiveCompressedSize(); } else { - gObjectData += (LLUnit)mesgsys->getReceiveSize(); + gObjectData += (LLUnit)mesgsys->getReceiveSize(); } gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index be477f7f9a..7ddee48b38 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -290,13 +290,13 @@ F32 gAveLandCompression = 0.f, gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f; -LLUnit gTotalWorldData = 0, +LLUnit gTotalWorldData = 0, gTotalObjectData = 0, gTotalTextureData = 0; U32 gSimPingCount = 0; -LLUnit gObjectData = 0; +LLUnit gObjectData = 0; F32 gAvgSimPing = 0.f; -LLUnit gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0}; +LLUnit gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0}; extern U32 gVisCompared; extern U32 gVisTested; @@ -334,8 +334,8 @@ void update_statistics() typedef LLInstanceTracker, std::string> trace_type_t; - LLUnit idle_secs = last_frame_recording.getSum(*trace_type_t::getInstance("Idle")); - LLUnit network_secs = last_frame_recording.getSum(*trace_type_t::getInstance("Network")); + LLUnit idle_secs = last_frame_recording.getSum(*trace_type_t::getInstance("Idle")); + LLUnit network_secs = last_frame_recording.getSum(*trace_type_t::getInstance("Network")); record(LLStatViewer::FRAME_STACKTIME, last_frame_recording.getSum(*trace_type_t::getInstance("Frame"))); record(LLStatViewer::UPDATE_STACKTIME, idle_secs - network_secs); diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index bfba7bca9a..4e48a61264 100755 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -331,7 +331,7 @@ void update_statistics(); void send_stats(); extern LLFrameTimer gTextureTimer; -extern LLUnit gTotalTextureData; -extern LLUnit gTotalObjectData; -extern LLUnit gTotalTextureBytesPerBoostLevel[] ; +extern LLUnit gTotalTextureData; +extern LLUnit gTotalObjectData; +extern LLUnit gTotalTextureBytesPerBoostLevel[] ; #endif // LL_LLVIEWERSTATS_H diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index e0a88bfad6..f468df0674 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -66,8 +66,8 @@ /////////////////////////////////////////////////////////////////////////////// // extern -const LLUnit gMinVideoRam = 32; -const LLUnit gMaxVideoRam = 512; +const LLUnit gMinVideoRam = 32; +const LLUnit gMaxVideoRam = 512; // statics @@ -88,11 +88,11 @@ S32 LLViewerTexture::sAuxCount = 0; LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; F32 LLViewerTexture::sDesiredDiscardScale = 1.1f; -LLUnit LLViewerTexture::sBoundTextureMemory = 0; -LLUnit LLViewerTexture::sTotalTextureMemory = 0; -LLUnit LLViewerTexture::sMaxBoundTextureMem = 0; -LLUnit LLViewerTexture::sMaxTotalTextureMem = 0; -LLUnit LLViewerTexture::sMaxDesiredTextureMem = 0 ; +LLUnit LLViewerTexture::sBoundTextureMemory = 0; +LLUnit LLViewerTexture::sTotalTextureMemory = 0; +LLUnit LLViewerTexture::sMaxBoundTextureMem = 0; +LLUnit LLViewerTexture::sMaxTotalTextureMem = 0; +LLUnit LLViewerTexture::sMaxDesiredTextureMem = 0 ; S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ; F32 LLViewerTexture::sCameraMovingBias = 0.0f ; S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size @@ -542,7 +542,7 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity sTotalTextureMemory >= sMaxTotalTextureMem) { //when texture memory overflows, lower down the threshold to release the textures more aggressively. - sMaxDesiredTextureMem = llmin(sMaxDesiredTextureMem * 0.75f, LLUnit(gMaxVideoRam)); + sMaxDesiredTextureMem = llmin(sMaxDesiredTextureMem * 0.75f, LLUnit(gMaxVideoRam)); // If we are using more texture memory than we should, // scale up the desired discard level diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index e939731cf2..529b812f41 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -39,8 +39,8 @@ #include #include -extern const LLUnit gMinVideoRam; -extern const LLUnit gMaxVideoRam; +extern const LLUnit gMinVideoRam; +extern const LLUnit gMaxVideoRam; class LLFace; class LLImageGL ; @@ -205,11 +205,11 @@ public: static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; static F32 sDesiredDiscardScale; - static LLUnit sBoundTextureMemory; - static LLUnit sTotalTextureMemory; - static LLUnit sMaxBoundTextureMem; - static LLUnit sMaxTotalTextureMem; - static LLUnit sMaxDesiredTextureMem ; + static LLUnit sBoundTextureMemory; + static LLUnit sTotalTextureMemory; + static LLUnit sMaxBoundTextureMem; + static LLUnit sMaxTotalTextureMem; + static LLUnit sMaxDesiredTextureMem ; static S8 sCameraMovingDiscardBias; static F32 sCameraMovingBias; static S32 sMaxSculptRez ; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 349849a267..97f7baa98d 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -738,7 +738,7 @@ public: { if(gTotalTextureBytesPerBoostLevel[i] > 0) { - addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, LLUnit(gTotalTextureBytesPerBoostLevel[i]).value())); + addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, LLUnit(gTotalTextureBytesPerBoostLevel[i]).value())); ypos += y_inc; } } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index dd5c153d55..7cf30e1661 100755 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2792,7 +2792,7 @@ void LLPipeline::updateGeom(F32 max_dtime) S32 count = 0; - max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, LLUnitImplicit(max_dtime)); + max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, LLUnitImplicit(max_dtime)); LLSpatialGroup* last_group = NULL; LLSpatialBridge* last_bridge = NULL; -- cgit v1.2.3 From 3f2de87340b1c831ea59e4a3ca960d49f343c9fd Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Mon, 17 Jun 2013 01:18:21 -0700 Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics added getAs and setAs to LLUnit to make it clearer how you specify units removed accidental 0-based indexing of periodicRecording history... should now be consistently 1-based, with 0 accessing current active recording removed per frame timer updates of all historical timer bars in fast timer display added missing assignment operator to recordings --- indra/llcommon/llfasttimer.cpp | 6 +- indra/llcommon/lltrace.h | 16 ++- indra/llcommon/lltracerecording.cpp | 23 ++- indra/llcommon/lltracerecording.h | 2 + indra/llcommon/llunit.h | 182 ++++++++++++------------ indra/llcommon/tests/llunits_test.cpp | 8 +- indra/newview/llfasttimerview.cpp | 257 ++++++++++++++++++++-------------- indra/newview/llfasttimerview.h | 31 ++-- indra/newview/llscenemonitor.cpp | 2 +- 9 files changed, 291 insertions(+), 236 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index 809a0327ca..d9670891f8 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -365,11 +365,11 @@ void TimeBlock::dumpCurTimes() ++it) { TimeBlock* timerp = (*it); - LLUnit total_time_ms = last_frame_recording.getSum(*timerp); + LLUnit total_time = last_frame_recording.getSum(*timerp); U32 num_calls = last_frame_recording.getSum(timerp->callCount()); // Don't bother with really brief times, keep output concise - if (total_time_ms < 0.1) continue; + if (total_time < LLUnit(0.1)) continue; std::ostringstream out_str; TimeBlock* parent_timerp = timerp; @@ -380,7 +380,7 @@ void TimeBlock::dumpCurTimes() } out_str << timerp->getName() << " " - << std::setprecision(3) << total_time_ms.as().value() << " ms, " + << std::setprecision(3) << total_time.getAs() << " ms, " << num_calls << " calls"; llinfos << out_str.str() << llendl; diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index 1bf853c5c0..cd377531e8 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -66,6 +66,16 @@ typedef LLUnit Kilometers; typedef LLUnit Centimeters; typedef LLUnit Millimeters; + +template +T storage_value(T val) { return val; } + +template +STORAGE_TYPE storage_value(LLUnit val) { return val.value(); } + +template +STORAGE_TYPE storage_value(LLUnitImplicit val) { return val.value(); } + void init(); void cleanup(); bool isInitialized(); @@ -678,7 +688,7 @@ template void record(EventStatHandle& measurement, VALUE_T value) { T converted_value(value); - measurement.getPrimaryAccumulator()->record(LLUnits::storageValue(converted_value)); + measurement.getPrimaryAccumulator()->record(storage_value(converted_value)); } template @@ -700,7 +710,7 @@ template void sample(SampleStatHandle& measurement, VALUE_T value) { T converted_value(value); - measurement.getPrimaryAccumulator()->sample(LLUnits::storageValue(converted_value)); + measurement.getPrimaryAccumulator()->sample(storage_value(converted_value)); } template @@ -722,7 +732,7 @@ template void add(CountStatHandle& count, VALUE_T value) { T converted_value(value); - count.getPrimaryAccumulator()->add(LLUnits::storageValue(converted_value)); + count.getPrimaryAccumulator()->add(storage_value(converted_value)); } diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index ff90da3822..f2c5941011 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -121,22 +121,27 @@ Recording::Recording() } Recording::Recording( const Recording& other ) +{ + *this = other; +} + +Recording& Recording::operator = (const Recording& other) { // this will allow us to seamlessly start without affecting any data we've acquired from other setPlayState(PAUSED); Recording& mutable_other = const_cast(other); + mutable_other.update(); EPlayState other_play_state = other.getPlayState(); - mutable_other.pause(); - mBuffers = other.mBuffers; + mBuffers = mutable_other.mBuffers; LLStopWatchControlsMixin::setPlayState(other_play_state); - mutable_other.setPlayState(other_play_state); // above call will clear mElapsedSeconds as a side effect, so copy it here mElapsedSeconds = other.mElapsedSeconds; mSamplingTimer = other.mSamplingTimer; + return *this; } @@ -444,12 +449,8 @@ void PeriodicRecording::nextPeriod() void PeriodicRecording::appendRecording(Recording& recording) { - // if I have a recording of any length, then close it off and start a fresh one - if (getCurRecording().getDuration().value()) - { - nextPeriod(); - } getCurRecording().appendRecording(recording); + nextPeriod(); } @@ -460,12 +461,6 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) getCurRecording().update(); other.getCurRecording().update(); - // if I have a recording of any length, then close it off and start a fresh one - if (getCurRecording().getDuration().value()) - { - nextPeriod(); - } - if (mAutoResize) { S32 other_index = (other.mCurPeriod + 1) % other.mRecordingPeriods.size(); diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index e3cef77b06..b839e85de0 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -135,6 +135,8 @@ namespace LLTrace Recording(const Recording& other); ~Recording(); + Recording& operator = (const Recording& other); + // accumulate data from subsequent, non-overlapping recording void appendRecording(const Recording& other); diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h index 5b961c81f0..5229fe69d7 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -30,31 +30,7 @@ #include "stdtypes.h" #include "llpreprocessor.h" #include "llerrorlegacy.h" - -namespace LLUnits -{ - -template -struct Convert -{ - static VALUE_TYPE get(VALUE_TYPE val) - { - // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template - llstatic_assert_template(DERIVED_UNITS_TAG, false, "Cannot convert between types."); - return val; - } -}; - -template -struct Convert -{ - static VALUE_TYPE get(VALUE_TYPE val) - { - return val; - } -}; - -} +#include template struct LLUnit @@ -70,7 +46,7 @@ struct LLUnit // unit initialization and conversion template LLUnit(LLUnit other) - : mValue(convert(other)) + : mValue(convert(other).mValue) {} bool operator == (const self_t& other) @@ -89,7 +65,7 @@ struct LLUnit template self_t& operator = (LLUnit other) { - mValue = convert(other); + mValue = convert(other).mValue; return *this; } @@ -98,11 +74,17 @@ struct LLUnit return mValue; } - template LLUnit as() + template + STORAGE_TYPE getAs() { - return LLUnit(*this); + return LLUnit(*this).value(); } + template + STORAGE_TYPE setAs(STORAGE_TYPE val) + { + *this = LLUnit(val); + } void operator += (storage_t value) { @@ -112,7 +94,7 @@ struct LLUnit template void operator += (LLUnit other) { - mValue += convert(other); + mValue += convert(other).mValue; } void operator -= (storage_t value) @@ -123,7 +105,7 @@ struct LLUnit template void operator -= (LLUnit other) { - mValue -= convert(other); + mValue -= convert(other).mValue; } void operator *= (storage_t multiplicand) @@ -151,19 +133,13 @@ struct LLUnit } template - static storage_t convert(LLUnit v) + static self_t convert(LLUnit v) { - return (storage_t)LLUnits::Convert::get((STORAGE_TYPE) - LLUnits::Convert::get(v.value())); + self_t result; + ll_convert_units(v, result); + return result; } - template - static storage_t convert(LLUnit v) - { - return (storage_t)(v.value()); - } - - protected: storage_t mValue; }; @@ -192,6 +168,39 @@ struct LLUnitImplicit : public LLUnit } }; + +template +LL_FORCE_INLINE void ll_convert_units(LLUnit in, LLUnit& out, ...) +{ + static_assert(boost::is_same::value + || !boost::is_same::value + || !boost::is_same::value, + "invalid conversion"); + + if (boost::is_same::value) + { + if (boost::is_same::value) + { + // T1 and T2 fully reduced and equal...just copy + out = (S2)in.value(); + } + else + { + // reduce T2 + LLUnit new_out; + ll_convert_units(in, new_out); + ll_convert_units(new_out, out); + } + } + else + { + // reduce T1 + LLUnit new_in; + ll_convert_units(in, new_in); + ll_convert_units(new_in, out); + } +} + // // operator + // @@ -415,17 +424,11 @@ struct LLGetUnitLabel > static const char* getUnitLabel() { return T::getUnitLabel(); } }; -// -// Unit declarations -// -namespace LLUnits -{ - template -struct LinearOps +struct LLUnitLinearOps { - typedef LinearOps self_t; - LinearOps(VALUE_TYPE val) : mValue (val) {} + typedef LLUnitLinearOps self_t; + LLUnitLinearOps(VALUE_TYPE val) : mValue (val) {} operator VALUE_TYPE() const { return mValue; } VALUE_TYPE mValue; @@ -456,11 +459,11 @@ struct LinearOps }; template -struct InverseLinearOps +struct LLUnitInverseLinearOps { - typedef InverseLinearOps self_t; + typedef LLUnitInverseLinearOps self_t; - InverseLinearOps(VALUE_TYPE val) : mValue (val) {} + LLUnitInverseLinearOps(VALUE_TYPE val) : mValue (val) {} operator VALUE_TYPE() const { return mValue; } VALUE_TYPE mValue; @@ -489,16 +492,6 @@ struct InverseLinearOps } }; - -template -T storageValue(T val) { return val; } - -template -STORAGE_TYPE storageValue(LLUnit val) { return val.value(); } - -template -STORAGE_TYPE storageValue(LLUnitImplicit val) { return val.value(); } - #define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }} @@ -507,57 +500,58 @@ struct unit_name { \ typedef base_unit_name base_unit_t; \ static const char* getUnitLabel() { return unit_label; } \ -}; \ -template \ -struct Convert \ -{ \ - static STORAGE_TYPE get(STORAGE_TYPE val) \ - { \ - return (LinearOps(val) conversion_operation).mValue; \ - } \ }; \ \ -template \ -struct Convert \ +template \ +void ll_convert_units(LLUnit in, LLUnit& out) \ { \ - static STORAGE_TYPE get(STORAGE_TYPE val) \ - { \ - return (InverseLinearOps(val) conversion_operation).mValue; \ - } \ -} + out = (S2)(LLUnitLinearOps(in.value()) conversion_operation).mValue; \ +} \ + \ +template \ +void ll_convert_units(LLUnit in, LLUnit& out) \ +{ \ + out = (S2)(LLUnitInverseLinearOps(in.value()) conversion_operation).mValue; \ +} +// +// Unit declarations +// + +namespace LLUnits +{ LL_DECLARE_BASE_UNIT(Bytes, "B"); LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, * 1000); -LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Bytes, * 1000 * 1000); -LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Bytes, * 1000 * 1000 * 1000); +LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, * 1000); LL_DECLARE_DERIVED_UNIT(Kibibytes, "KiB", Bytes, * 1024); -LL_DECLARE_DERIVED_UNIT(Mibibytes, "MiB", Bytes, * 1024 * 1024); -LL_DECLARE_DERIVED_UNIT(Gibibytes, "GiB", Bytes, * 1024 * 1024 * 1024); +LL_DECLARE_DERIVED_UNIT(Mibibytes, "MiB", Kibibytes, * 1024); +LL_DECLARE_DERIVED_UNIT(Gibibytes, "GiB", Mibibytes, * 1024); LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, / 8); -LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bytes, * (1000 / 8)); -LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Bytes, * (1000 / 8)); -LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Bytes, * (1000 * 1000 * 1000 / 8)); -LL_DECLARE_DERIVED_UNIT(Kibibits, "Kib", Bytes, * (1024 / 8)); -LL_DECLARE_DERIVED_UNIT(Mibibits, "Mib", Bytes, * (1024 / 8)); -LL_DECLARE_DERIVED_UNIT(Gibibits, "Gib", Bytes, * (1024 * 1024 * 1024 / 8)); +LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bytes, * 1000 / 8); +LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, * 1000 / 8); +LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, * 1000 / 8); +LL_DECLARE_DERIVED_UNIT(Kibibits, "Kib", Bytes, * 1024 / 8); +LL_DECLARE_DERIVED_UNIT(Mibibits, "Mib", Kibibits, * 1024 / 8); +LL_DECLARE_DERIVED_UNIT(Gibibits, "Gib", Mibibits, * 1024 / 8); LL_DECLARE_BASE_UNIT(Seconds, "s"); LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, * 60); LL_DECLARE_DERIVED_UNIT(Hours, "h", Seconds, * 60 * 60); LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, / 1000); -LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Seconds, / 1000000); -LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Seconds, / 1000000000); +LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, / 1000); +LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, / 1000); LL_DECLARE_BASE_UNIT(Meters, "m"); LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, * 1000); -LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100); -LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, * 1000); +LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, / 100); +LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, / 1000); LL_DECLARE_BASE_UNIT(Hertz, "Hz"); LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, * 1000); -LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Hertz, * 1000 * 1000); -LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Hertz, * 1000 * 1000 * 1000); +LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Kilohertz, * 1000); +LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, * 1000); LL_DECLARE_BASE_UNIT(Radians, "rad"); LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 0.01745329251994); diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp index 747e8d1827..04764f6c2f 100644 --- a/indra/llcommon/tests/llunits_test.cpp +++ b/indra/llcommon/tests/llunits_test.cpp @@ -35,7 +35,7 @@ namespace LLUnits // using powers of 2 to allow strict floating point equality LL_DECLARE_BASE_UNIT(Quatloos, "Quat"); LL_DECLARE_DERIVED_UNIT(Latinum, "Lat", Quatloos, * 4); - LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Quatloos, / 4); + LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, / 16); } namespace tut @@ -206,5 +206,11 @@ namespace tut S32 int_val = quatloos_implicit; ensure(int_val == 16); + + // conversion of implicits + LLUnitImplicit latinum_implicit(2); + ensure(latinum_implicit == 2); + + ensure(latinum_implicit * 2 == quatloos_implicit); } } diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 8e061ec87c..231ece4bbd 100755 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -56,7 +56,7 @@ using namespace LLTrace; -static const S32 MAX_VISIBLE_HISTORY = 10; +static const S32 MAX_VISIBLE_HISTORY = 12; static const S32 LINE_GRAPH_HEIGHT = 240; static const S32 MIN_BAR_HEIGHT = 3; @@ -105,7 +105,7 @@ LLFastTimerView::LLFastTimerView(const LLSD& key) mPauseHistory(false), mRecording(512) { - mTimerBarRows.resize(MAX_VISIBLE_HISTORY); + mTimerBarRows.resize(512); } LLFastTimerView::~LLFastTimerView() @@ -272,32 +272,36 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) mHoverBarIndex = 0; } - S32 i = 0; - for(timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); - it != end_timer_tree(); - ++it, ++i) + TimerBarRow& row = mHoverBarIndex == 0 ? mAverageTimerRow : mTimerBarRows[mHoverBarIndex - 1]; + + TimerBar* hover_bar = NULL; + LLUnit mouse_time_offset = ((F32)(x - mBarRect.mLeft) / (F32)mBarRect.getWidth()) * mTotalTimeDisplay; + for (std::vector::iterator it = row.mBars.begin(), end_it = row.mBars.end(); + it != end_it; + ++it) { - // is mouse over bar for this timer? - TimerBarRow& row = mHoverBarIndex == 0 ? mAverageTimerRow : mTimerBarRows[mHoverBarIndex - 1]; - if (row.mBars[i].mVisibleRect.pointInRect(x, y - row.mBottom)) + if (it->mSelfStart > mouse_time_offset) { - mHoverID = (*it); - if (mHoverTimer != *it) - { - // could be that existing tooltip is for a parent and is thus - // covering region for this new timer, go ahead and unblock - // so we can create a new tooltip - LLToolTipMgr::instance().unblockToolTips(); - mHoverTimer = (*it); - } - - mToolTipRect = row.mBars[i].mVisibleRect; - mToolTipRect.translate(0, row.mBottom); + break; } + hover_bar = &(*it); + } - if ((*it)->getCollapsed()) + if (hover_bar) + { + mHoverID = hover_bar->mTimeBlock; + mHoverTimer = mHoverID; + if (mHoverTimer != mHoverID) { - it.skipDescendants(); + // could be that existing tooltip is for a parent and is thus + // covering region for this new timer, go ahead and unblock + // so we can create a new tooltip + LLToolTipMgr::instance().unblockToolTips(); + mHoverTimer = mHoverID; + mToolTipRect.set(mBarRect.mLeft + (hover_bar->mSelfStart / mTotalTimeDisplay) * mBarRect.getWidth(), + row.mTop, + mBarRect.mLeft + (hover_bar->mSelfStart / mTotalTimeDisplay) * mBarRect.getWidth(), + row.mBottom); } } } @@ -422,9 +426,14 @@ void LLFastTimerView::draw() void LLFastTimerView::onOpen(const LLSD& key) { - if (mRecording.getNumRecordedPeriods() == 0) + setPauseState(false); + mRecording.reset(); + mRecording.appendPeriodicRecording(LLTrace::get_frame_recording()); + for(std::deque::iterator it = mTimerBarRows.begin(), end_it = mTimerBarRows.end(); + it != end_it; + ++it) { - mRecording.appendPeriodicRecording(LLTrace::get_frame_recording()); + it->mBars.clear(); } } @@ -1077,6 +1086,7 @@ void LLFastTimerView::drawLineGraph() glLineWidth(3); } + llassert(idp->getIndex() < sTimerColors.size()); const F32 * col = sTimerColors[idp->getIndex()].mV;// ft_display_table[idx].color->mV; F32 alpha = 1.f; @@ -1191,6 +1201,7 @@ void LLFastTimerView::drawLegend( S32 y ) scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f); } bar_rect.stretch(scale_offset); + llassert(idp->getIndex() < sTimerColors.size()); gl_rect_2d(bar_rect, sTimerColors[idp->getIndex()]); LLUnit ms = 0; @@ -1262,7 +1273,7 @@ void LLFastTimerView::generateUniqueColors() { // generate unique colors { - sTimerColors.reserve(LLTrace::TimeBlock::getNumIndices()); + sTimerColors.resize(LLTrace::TimeBlock::getNumIndices()); sTimerColors[FTM_FRAME.getIndex()] = LLColor4::grey; F32 hue = 0.f; @@ -1283,6 +1294,7 @@ void LLFastTimerView::generateUniqueColors() LLColor4 child_color; child_color.setHSL(hue, saturation, lightness); + llassert(idp->getIndex() < sTimerColors.size()); sTimerColors[idp->getIndex()] = child_color; } } @@ -1377,7 +1389,7 @@ void LLFastTimerView::drawBorders( S32 y, const S32 x_start, S32 bar_height, S32 //history bars gl_rect_2d(x_start-5, by, getRect().getWidth()-5, LINE_GRAPH_HEIGHT-bar_height-dy-2, LLColor4::grey, FALSE); - by = LINE_GRAPH_HEIGHT-bar_height-dy-7; + by = LINE_GRAPH_HEIGHT-dy; //line graph mGraphRect = LLRect(x_start-5, by, getRect().getWidth()-5, 5); @@ -1391,21 +1403,21 @@ void LLFastTimerView::updateTotalTime() switch(mDisplayMode) { case 0: - mTotalTimeDisplay = mRecording.getPeriodMean(FTM_FRAME)*2; + mTotalTimeDisplay = mRecording.getPeriodMean(FTM_FRAME, 100)*2; break; case 1: - mTotalTimeDisplay = mAllTimeMax; + mTotalTimeDisplay = mRecording.getPeriodMax(FTM_FRAME); break; case 2: // Calculate the max total ticks for the current history - mTotalTimeDisplay = mRecording.getPeriodMax(FTM_FRAME); + mTotalTimeDisplay = mRecording.getPeriodMax(FTM_FRAME, 20); break; default: mTotalTimeDisplay = LLUnit(100); break; } - mTotalTimeDisplay = LLUnit(llceil(mTotalTimeDisplay.as().value() / 20.f) * 20.f); + mTotalTimeDisplay = LLUnit(llceil(mTotalTimeDisplay.getAs() / 20.f) * 20.f); } void LLFastTimerView::drawBars() @@ -1432,41 +1444,44 @@ void LLFastTimerView::drawBars() gGL.getTexUnit(0)->bind(bar_image->getImage()); { - const S32 histmax = llmin((S32)mRecording.getNumRecordedPeriods(), MAX_VISIBLE_HISTORY); - - llassert(mTimerBarRows.size() >= histmax); + const S32 histmax = (S32)mRecording.getNumRecordedPeriods(); // update widths updateTimerBarWidths(&FTM_FRAME, mAverageTimerRow, -1); - mAverageTimerRow.mBars[0].mVisibleRect = LLRect(mBarRect.mLeft, 0, mBarRect.mLeft + mAverageTimerRow.mBars[0].mWidth, -bar_height); - updateTimerBarFractions(&FTM_FRAME, mAverageTimerRow); + updateTimerBarOffsets(&FTM_FRAME, mAverageTimerRow); - for (S32 history_index = 0; history_index < histmax; history_index++) + for (S32 history_index = 1; history_index <= histmax; history_index++) { - TimerBarRow& row = mTimerBarRows[history_index]; + llassert(history_index <= mTimerBarRows.size()); + TimerBarRow& row = mTimerBarRows[history_index - 1]; if (row.mBars.empty()) { row.mBars.reserve(LLInstanceTracker::instanceCount()); updateTimerBarWidths(&FTM_FRAME, row, history_index); - row.mBars[0].mVisibleRect = LLRect(mBarRect.mLeft, 0, mBarRect.mLeft + row.mBars[0].mWidth, -1); - updateTimerBarFractions(&FTM_FRAME, row); + updateTimerBarOffsets(&FTM_FRAME, row); } } // draw bars - LLRect frame_bar_rect( mBarRect.mLeft, - bars_top, - mBarRect.mLeft + mAverageTimerRow.mBars[0].mWidth, - bars_top - bar_height); + LLRect frame_bar_rect; + frame_bar_rect.setLeftTopAndSize(mBarRect.mLeft, + bars_top, + llround((mAverageTimerRow.mBars[0].mTotalTime / mTotalTimeDisplay) * mBarRect.getWidth()), + bar_height); + mAverageTimerRow.mTop = frame_bar_rect.mTop; mAverageTimerRow.mBottom = frame_bar_rect.mBottom; - drawBar(&FTM_FRAME, frame_bar_rect, mAverageTimerRow, image_width, image_height, false); + drawBar(frame_bar_rect, mAverageTimerRow, image_width, image_height); frame_bar_rect.translate(0, -(bar_height + vpad + bar_height)); for(S32 bar_index = mScrollIndex; bar_index < llmin(histmax, mScrollIndex + MAX_VISIBLE_HISTORY); ++bar_index) { + llassert(bar_index < mTimerBarRows.size()); TimerBarRow& row = mTimerBarRows[bar_index]; + row.mTop = frame_bar_rect.mTop; row.mBottom = frame_bar_rect.mBottom; - drawBar(&FTM_FRAME, frame_bar_rect, row, image_width, image_height, false); + frame_bar_rect.mRight = frame_bar_rect.mLeft + + llround((row.mBars[0].mTotalTime / mTotalTimeDisplay) * mBarRect.getWidth()); + drawBar(frame_bar_rect, row, image_width, image_height); frame_bar_rect.translate(0, -(bar_height + vpad)); } @@ -1477,97 +1492,115 @@ void LLFastTimerView::drawBars() static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_WIDTHS("Update timer bar widths"); -S32 LLFastTimerView::updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, bool visible) +LLUnit LLFastTimerView::updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, bool visible) { - std::vector& bars = row.mBars; LLFastTimer _(FTM_UPDATE_TIMER_BAR_WIDTHS); - const F32 self_time_frame_fraction = history_index == -1 - ? (mRecording.getPeriodMean(time_block->selfTime()) / mTotalTimeDisplay) - : (mRecording.getPrevRecording(history_index).getSum(time_block->selfTime()) / mTotalTimeDisplay); + const LLUnit self_time = history_index == -1 + ? mRecording.getPeriodMean(time_block->selfTime()) + : mRecording.getPrevRecording(history_index).getSum(time_block->selfTime()); - const S32 self_time_width = llround(self_time_frame_fraction * (F32)mBarRect.getWidth()); - S32 full_width = self_time_width; + LLUnit full_time = self_time; // reserve a spot for this bar to be rendered before its children // even though we don't know its size yet + std::vector& bars = row.mBars; + S32 bar_index = bars.size(); bars.push_back(TimerBar()); - TimerBar& timer_bar = bars.back(); const bool children_visible = visible && !time_block->getCollapsed(); for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); it != end_it; ++it) { - full_width += updateTimerBarWidths(*it, row, history_index, children_visible); + full_time += updateTimerBarWidths(*it, row, history_index, children_visible); } - timer_bar.mWidth = full_width; - timer_bar.mSelfWidth = self_time_width; - timer_bar.mTimeBlock = time_block; - timer_bar.mVisible = visible; + TimerBar& timer_bar = bars[bar_index]; + timer_bar.mTotalTime = full_time; + timer_bar.mSelfTime = self_time; + timer_bar.mTimeBlock = time_block; + timer_bar.mVisible = visible; - return full_width; + return full_time; } static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_FRACTIONS("Update timer bar fractions"); -S32 LLFastTimerView::updateTimerBarFractions(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 timer_bar_index) +S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 timer_bar_index) { - std::vector& bars = row.mBars; LLFastTimer _(FTM_UPDATE_TIMER_BAR_FRACTIONS); + + std::vector& bars = row.mBars; + llassert(timer_bar_index < bars.size()); TimerBar& timer_bar = bars[timer_bar_index]; - S32 child_time_width = timer_bar.mWidth - timer_bar.mSelfWidth; - LLRect children_rect = timer_bar.mVisibleRect; + const LLUnit child_time_width = timer_bar.mTotalTime - timer_bar.mSelfTime; + timer_bar.mChildrenStart = timer_bar.mSelfStart; if (mDisplayCenter == ALIGN_CENTER) { - children_rect.mLeft += timer_bar.mSelfWidth / 2; + timer_bar.mChildrenStart += timer_bar.mSelfTime / 2; } else if (mDisplayCenter == ALIGN_RIGHT) { - children_rect.mLeft += timer_bar.mSelfWidth; + timer_bar.mChildrenStart += timer_bar.mSelfTime; } - children_rect.mRight = children_rect.mLeft + timer_bar.mWidth - timer_bar.mSelfWidth; - - timer_bar.mChildrenRect = children_rect; + timer_bar.mChildrenEnd = timer_bar.mChildrenStart + timer_bar.mTotalTime - timer_bar.mSelfTime; //now loop through children and figure out portion of bar image covered by each bar, now that we know the //sum of all children - if (!time_block->getCollapsed()) + F32 bar_fraction_start = 0.f; + TimerBar* last_child_timer_bar = NULL; + + bool first_child = true; + for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); + it != end_it; + ++it) { - F32 bar_fraction_start = 0.f; - for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); - it != end_it; - ++it) + timer_bar_index++; + + llassert(timer_bar_index < bars.size()); + TimerBar& child_timer_bar = bars[timer_bar_index]; + TimeBlock* child_time_block = *it; + + if (last_child_timer_bar) { - timer_bar_index++; + last_child_timer_bar->mLastChild = false; + } + child_timer_bar.mLastChild = true; + last_child_timer_bar = &child_timer_bar; - TimerBar& child_timer_bar = bars[timer_bar_index]; - TimeBlock* child_time_block = *it; + child_timer_bar.mFirstChild = first_child; + if (first_child) + { + first_child = false; + } - child_timer_bar.mStartFraction = bar_fraction_start; - child_timer_bar.mEndFraction = child_time_width > 0 - ? bar_fraction_start + (F32)child_timer_bar.mWidth / child_time_width - : 1.f; - child_timer_bar.mVisibleRect.set(children_rect.mLeft + llround(child_timer_bar.mStartFraction * children_rect.getWidth()), - children_rect.mTop, - children_rect.mLeft + llround(child_timer_bar.mEndFraction * children_rect.getWidth()), - children_rect.mBottom); + child_timer_bar.mStartFraction = bar_fraction_start; + child_timer_bar.mEndFraction = child_time_width > 0 + ? bar_fraction_start + child_timer_bar.mTotalTime / child_time_width + : 1.f; + child_timer_bar.mSelfStart = timer_bar.mChildrenStart + + child_timer_bar.mStartFraction + * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart); + child_timer_bar.mSelfEnd = timer_bar.mChildrenStart + + child_timer_bar.mEndFraction + * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart); - timer_bar_index = updateTimerBarFractions(child_time_block, row, timer_bar_index); + timer_bar_index = updateTimerBarOffsets(child_time_block, row, timer_bar_index); - bar_fraction_start = child_timer_bar.mEndFraction; - } + bar_fraction_start = child_timer_bar.mEndFraction; } return timer_bar_index; } -S32 LLFastTimerView::drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, S32 bar_index) +S32 LLFastTimerView::drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, S32 bar_index) { + llassert(bar_index < row.mBars.size()); TimerBar& timer_bar = row.mBars[bar_index]; + LLTrace::TimeBlock* time_block = timer_bar.mTimeBlock; hovered |= mHoverID == time_block; // animate scale of bar when hovering over that particular timer - if (bar_rect.getWidth() > 0) + if ((F32)bar_rect.getWidth() * (timer_bar.mEndFraction - timer_bar.mStartFraction) > 2.f) { LLRect render_rect(bar_rect); S32 scale_offset = 0; @@ -1578,8 +1611,9 @@ S32 LLFastTimerView::drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, Ti render_rect.mBottom -= scale_offset; } + llassert(time_block->getIndex() < sTimerColors.size()); LLColor4 color = sTimerColors[time_block->getIndex()]; - if (!hovered) color = lerp(color, LLColor4::grey, 0.8f); + if (!hovered) color = lerp(color, LLColor4::grey, 0.2f); gGL.color4fv(color.mV); gl_segmented_rect_2d_fragment_tex(render_rect, image_width, image_height, @@ -1587,26 +1621,33 @@ S32 LLFastTimerView::drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, Ti timer_bar.mStartFraction, timer_bar.mEndFraction); } - if (!time_block->getCollapsed()) + LLRect children_rect; + children_rect.mLeft = llround(timer_bar.mChildrenStart / mTotalTimeDisplay * (F32)mBarRect.getWidth()) + mBarRect.mLeft; + children_rect.mRight = llround(timer_bar.mChildrenEnd / mTotalTimeDisplay * (F32)mBarRect.getWidth()) + mBarRect.mLeft; + + if (bar_rect.getHeight() > MIN_BAR_HEIGHT) { - for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); it != end_it; ++it) + // shrink as we go down a level + children_rect.mTop = bar_rect.mTop - 1; + children_rect.mBottom = bar_rect.mBottom + 1; + } + else + { + children_rect.mTop = bar_rect.mTop; + children_rect.mBottom = bar_rect.mBottom; + } + + bar_index++; + const U32 num_bars = row.mBars.size(); + if (bar_index < num_bars && row.mBars[bar_index].mFirstChild) + { + bool is_last = false; + do { - ++bar_index; - LLRect children_rect = timer_bar.mChildrenRect; - children_rect.translate(0, row.mBottom); - if (bar_rect.getHeight() > MIN_BAR_HEIGHT) - { - // shrink as we go down a level - children_rect.mTop = bar_rect.mTop - 1; - children_rect.mBottom = bar_rect.mBottom + 1; - } - else - { - children_rect.mTop = bar_rect.mTop; - children_rect.mBottom = bar_rect.mBottom; - } - bar_index = drawBar(*it, children_rect, row, image_width, image_height, hovered, bar_index); + is_last = row.mBars[bar_index].mLastChild; + bar_index = drawBar(children_rect, row, image_width, image_height, hovered, bar_index); } + while(!is_last && bar_index < num_bars); } return bar_index; diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index c20cadd6d7..d9ae6348da 100755 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -80,31 +80,38 @@ private: struct TimerBar { TimerBar() - : mWidth(0), - mSelfWidth(0), + : mTotalTime(0), + mSelfTime(0), mVisible(true), mStartFraction(0.f), - mEndFraction(1.f) + mEndFraction(1.f), + mFirstChild(false), + mLastChild(false) {} - S32 mWidth; - S32 mSelfWidth; - LLRect mVisibleRect, - mChildrenRect; + LLUnit mTotalTime, + mSelfTime, + mChildrenStart, + mChildrenEnd, + mSelfStart, + mSelfEnd; LLTrace::TimeBlock* mTimeBlock; - bool mVisible; + bool mVisible, + mFirstChild, + mLastChild; F32 mStartFraction, mEndFraction; }; struct TimerBarRow { - S32 mBottom; + S32 mBottom, + mTop; std::vector mBars; }; - S32 updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, bool visible = true); - S32 updateTimerBarFractions(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 timer_bar_index = 0); - S32 drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, S32 bar_index = 0); + LLUnit updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, bool visible = true); + S32 updateTimerBarOffsets(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 timer_bar_index = 0); + S32 drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered = false, S32 bar_index = 0); void setPauseState(bool pause_state); std::deque mTimerBarRows; diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 3d9e0ab4c3..8086745471 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -616,7 +616,7 @@ void LLSceneMonitor::dumpToFile(std::string file_name) for (S32 frame = 0; frame < frame_count; frame++) { - os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(*it).as().value(); + os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(*it).getAs(); } os << std::endl; -- cgit v1.2.3 From d136c4c29686c565b5a46503aa67a9c958b4145d Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 18 Jun 2013 23:41:53 -0700 Subject: SH-4246 FIX interesting: fast timers significantly decreases framerate removed implicit flushes on reads from recorders for better performance made sure stack timers were updated on recorder deactivate faster rendering and better ui for fast timer view --- indra/llcommon/llfasttimer.cpp | 77 +++-- indra/llcommon/llfasttimer.h | 4 + indra/llcommon/lltrace.h | 19 +- indra/llcommon/lltracerecording.cpp | 38 +-- indra/llcommon/lltracethreadrecorder.cpp | 1 + indra/llcommon/tests/llunits_test.cpp | 3 + indra/newview/llfasttimerview.cpp | 316 +++++++++++---------- indra/newview/llfasttimerview.h | 33 +-- .../skins/default/xui/en/floater_fast_timers.xml | 69 +++++ 9 files changed, 315 insertions(+), 245 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index d9670891f8..4da9c3fd6c 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -178,43 +178,38 @@ TimeBlockTreeNode& TimeBlock::getTreeNode() const return *nodep; } -static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times"); -// not thread safe, so only call on main thread -//static -void TimeBlock::processTimes() +void TimeBlock::bootstrapTimerTree() { - LLFastTimer _(FTM_PROCESS_TIMES); - get_clock_count(); // good place to calculate clock frequency - U64 cur_time = getCPUClockCount64(); - - // set up initial tree for (LLInstanceTracker::instance_iter begin_it = LLInstanceTracker::beginInstances(), end_it = LLInstanceTracker::endInstances(), it = begin_it; it != end_it; ++it) { TimeBlock& timer = *it; if (&timer == &TimeBlock::getRootTimeBlock()) continue; - + // bootstrap tree construction by attaching to last timer to be on stack // when this timer was called if (timer.getParent() == &TimeBlock::getRootTimeBlock()) { TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator(); - + if (accumulator->mLastCaller) { timer.setParent(accumulator->mLastCaller); accumulator->mParent = accumulator->mLastCaller; } - // no need to push up tree on first use, flag can be set spuriously + // no need to push up tree on first use, flag can be set spuriously accumulator->mMoveUpTree = false; } } +} - // bump timers up tree if they have been flagged as being in the wrong place - // do this in a bottom up order to promote descendants first before promoting ancestors - // this preserves partial order derived from current frame's observations +// bump timers up tree if they have been flagged as being in the wrong place +// do this in a bottom up order to promote descendants first before promoting ancestors +// this preserves partial order derived from current frame's observations +void TimeBlock::incrementalUpdateTimerTree() +{ for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(TimeBlock::getRootTimeBlock()); it != end_timer_tree_bottom_up(); ++it) @@ -240,27 +235,35 @@ void TimeBlock::processTimes() LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() << " to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL; timerp->setParent(timerp->getParent()->getParent()); - accumulator->mParent = timerp->getParent(); - accumulator->mMoveUpTree = false; + accumulator->mParent = timerp->getParent(); + accumulator->mMoveUpTree = false; // don't bubble up any ancestors until descendants are done bubbling up - // as ancestors may call this timer only on certain paths, so we want to resolve - // child-most block locations before their parents + // as ancestors may call this timer only on certain paths, so we want to resolve + // child-most block locations before their parents it.skipAncestors(); } } } +} + + +void TimeBlock::updateTimes() +{ + U64 cur_time = getCPUClockCount64(); // walk up stack of active timers and accumulate current time while leaving timing structures active - BlockTimerStackRecord* stack_record = ThreadTimerStack::getInstance(); - BlockTimer* cur_timer = stack_record->mActiveTimer; - TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator(); + BlockTimerStackRecord* stack_record = ThreadTimerStack::getInstance(); + BlockTimer* cur_timer = stack_record->mActiveTimer; + TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator(); while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self { U64 cumulative_time_delta = cur_time - cur_timer->mStartTime; - accumulator->mTotalTimeCounter += cumulative_time_delta - (accumulator->mTotalTimeCounter - cur_timer->mBlockStartTotalTimeCounter); + accumulator->mTotalTimeCounter += cumulative_time_delta + - (accumulator->mTotalTimeCounter + - cur_timer->mBlockStartTotalTimeCounter); accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime; stack_record->mChildTime = 0; @@ -268,11 +271,28 @@ void TimeBlock::processTimes() cur_timer->mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter; stack_record = &cur_timer->mParentTimerData; - accumulator = stack_record->mTimeBlock->getPrimaryAccumulator(); - cur_timer = stack_record->mActiveTimer; + accumulator = stack_record->mTimeBlock->getPrimaryAccumulator(); + cur_timer = stack_record->mActiveTimer; stack_record->mChildTime += cumulative_time_delta; } +} + +static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times"); + +// not thread safe, so only call on main thread +//static +void TimeBlock::processTimes() +{ + LLFastTimer _(FTM_PROCESS_TIMES); + get_clock_count(); // good place to calculate clock frequency + + // set up initial tree + bootstrapTimerTree(); + + incrementalUpdateTimerTree(); + + updateTimes(); // reset for next frame for (LLInstanceTracker::instance_iter it = LLInstanceTracker::beginInstances(), @@ -288,14 +308,13 @@ void TimeBlock::processTimes() } } - std::vector::iterator TimeBlock::beginChildren() - { +{ return getTreeNode().mChildren.begin(); - } +} std::vector::iterator TimeBlock::endChildren() - { +{ return getTreeNode().mChildren.end(); } diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index fdc6997d45..e800befd9f 100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -115,6 +115,7 @@ public: static void pushLog(LLSD sd); static void setLogLock(LLMutex* mutex); static void writeLog(std::ostream& os); + static void updateTimes(); // dumps current cumulative frame stats to log // call nextFrame() to reset timers @@ -262,6 +263,9 @@ public: // can be called multiple times in a frame, at any point static void processTimes(); + static void bootstrapTimerTree(); + static void incrementalUpdateTimerTree(); + // call this once a frame to periodically log timers static void logStats(); diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index cd377531e8..6292534a03 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -157,12 +157,12 @@ public: } } - void flush() + void flush(LLUnitImplicit time_stamp) { llassert(mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { - mStorage[i].flush(); + mStorage[i].flush(time_stamp); } } @@ -380,7 +380,7 @@ public: mLastValue = other ? other->mLastValue : 0; } - void flush() {} + void flush(LLUnitImplicit) {} F64 getSum() const { return mSum; } F64 getMin() const { return mMin; } @@ -512,9 +512,8 @@ public: mHasValue = other ? other->mHasValue : false; } - void flush() + void flush(LLUnitImplicit time_stamp) { - LLUnitImplicit time_stamp = LLTimer::getTotalSeconds(); LLUnitImplicit delta_time = time_stamp - mLastSampleTimeStamp; if (mHasValue) @@ -579,7 +578,7 @@ public: mSum = 0; } - void flush() {} + void flush(LLUnitImplicit) {} F64 getSum() const { return mSum; } @@ -614,7 +613,7 @@ public: TimeBlockAccumulator(); void addSamples(const self_t& other, bool /*append*/); void reset(const self_t* other); - void flush() {} + void flush(LLUnitImplicit) {} // // members @@ -780,10 +779,10 @@ struct MemStatAccumulator mDeallocatedCount = 0; } - void flush() + void flush(LLUnitImplicit time_stamp) { - mSize.flush(); - mChildSize.flush(); + mSize.flush(time_stamp); + mChildSize.flush(time_stamp); } SampleAccumulator mSize, diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index f2c5941011..33002929ea 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -107,7 +107,9 @@ void RecordingBuffers::reset(RecordingBuffers* other) void RecordingBuffers::flush() { - mSamples.flush(); + LLUnitImplicit time_stamp = LLTimer::getTotalSeconds(); + + mSamples.flush(time_stamp); } /////////////////////////////////////////////////////////////////////// @@ -205,7 +207,6 @@ void Recording::mergeRecording( const Recording& other) LLUnit Recording::getSum(const TraceType& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; - update(); return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond(); } @@ -213,14 +214,12 @@ LLUnit Recording::getSum(const TraceType Recording::getSum(const TraceType& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; - update(); return (F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond(); } U32 Recording::getSum(const TraceType& stat) { - update(); return mBuffers->mStackTimers[stat.getIndex()].mCalls; } @@ -228,7 +227,6 @@ LLUnit Recording::getPerSec(const TraceTypemStackTimers[stat.getIndex()]; - update(); return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()); } @@ -237,105 +235,88 @@ LLUnit Recording::getPerSec(const TraceTypemStackTimers[stat.getIndex()]; - update(); return (F64)(accumulator.mSelfTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()); } F32 Recording::getPerSec(const TraceType& stat) { - update(); return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value(); } LLUnit Recording::getMin(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMin(); } LLUnit Recording::getMean(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMean(); } LLUnit Recording::getMax(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMax(); } LLUnit Recording::getStandardDeviation(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation(); } LLUnit Recording::getLastValue(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue(); } LLUnit Recording::getMin(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin(); } LLUnit Recording::getMean(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean(); } LLUnit Recording::getMax(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax(); } LLUnit Recording::getStandardDeviation(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation(); } LLUnit Recording::getLastValue(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue(); } U32 Recording::getSum(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount; } U32 Recording::getSum(const TraceType& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount; } F64 Recording::getSum( const TraceType& stat ) { - update(); return mBuffers->mCounts[stat.getIndex()].getSum(); } F64 Recording::getSum( const TraceType& stat ) { - update(); return (F64)mBuffers->mEvents[stat.getIndex()].getSum(); } F64 Recording::getPerSec( const TraceType& stat ) { - update(); F64 sum = mBuffers->mCounts[stat.getIndex()].getSum(); return (sum != 0.0) ? (sum / mElapsedSeconds.value()) @@ -344,79 +325,66 @@ F64 Recording::getPerSec( const TraceType& stat ) U32 Recording::getSampleCount( const TraceType& stat ) { - update(); return mBuffers->mCounts[stat.getIndex()].getSampleCount(); } F64 Recording::getMin( const TraceType& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getMin(); } F64 Recording::getMax( const TraceType& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getMax(); } F64 Recording::getMean( const TraceType& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getMean(); } F64 Recording::getStandardDeviation( const TraceType& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getStandardDeviation(); } F64 Recording::getLastValue( const TraceType& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getLastValue(); } U32 Recording::getSampleCount( const TraceType& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getSampleCount(); } F64 Recording::getMin( const TraceType& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getMin(); } F64 Recording::getMax( const TraceType& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getMax(); } F64 Recording::getMean( const TraceType& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getMean(); } F64 Recording::getStandardDeviation( const TraceType& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getStandardDeviation(); } F64 Recording::getLastValue( const TraceType& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getLastValue(); } U32 Recording::getSampleCount( const TraceType& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getSampleCount(); } diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index c1a0700eff..54006f4e5b 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -111,6 +111,7 @@ ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringU if (mActiveRecordings.empty()) return mActiveRecordings.rend(); mActiveRecordings.back()->mPartialRecording.flush(); + TimeBlock::updateTimes(); active_recording_list_t::reverse_iterator it, end_it; for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend(); diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp index 04764f6c2f..a5df51f6de 100644 --- a/indra/llcommon/tests/llunits_test.cpp +++ b/indra/llcommon/tests/llunits_test.cpp @@ -56,6 +56,9 @@ namespace tut LLUnit float_quatloos; ensure(float_quatloos == 0.f); + LLUnit float_initialize_quatloos(1); + ensure(float_initialize_quatloos == 1.f); + LLUnit int_quatloos; ensure(int_quatloos == 0); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 231ece4bbd..1355b58f8b 100755 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -30,12 +30,14 @@ #include "llviewerwindow.h" #include "llrect.h" +#include "llcombobox.h" #include "llerror.h" #include "llgl.h" #include "llimagepng.h" #include "llrender.h" #include "llrendertarget.h" #include "lllocalcliprect.h" +#include "lllayoutstack.h" #include "llmath.h" #include "llfontgl.h" #include "llsdserialize.h" @@ -59,6 +61,8 @@ using namespace LLTrace; static const S32 MAX_VISIBLE_HISTORY = 12; static const S32 LINE_GRAPH_HEIGHT = 240; static const S32 MIN_BAR_HEIGHT = 3; +static const S32 RUNNING_AVERAGE_WIDTH = 100; +static const S32 NUM_FRAMES_HISTORY = 256; std::vector ft_display_idx; // line of table entry for display purposes (for collapse) @@ -95,17 +99,15 @@ LLFastTimerView::LLFastTimerView(const LLSD& key) : LLFloater(key), mHoverTimer(NULL), mDisplayMode(0), - mDisplayCenter(ALIGN_CENTER), - mDisplayCalls(false), - mDisplayHz(false), + mDisplayType(TIME), mScrollIndex(0), mHoverID(NULL), mHoverBarIndex(-1), mStatsIndex(-1), mPauseHistory(false), - mRecording(512) + mRecording(NUM_FRAMES_HISTORY) { - mTimerBarRows.resize(512); + mTimerBarRows.resize(NUM_FRAMES_HISTORY); } LLFastTimerView::~LLFastTimerView() @@ -172,7 +174,7 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) TimeBlock* LLFastTimerView::getLegendID(S32 y) { - S32 idx = (mBarRect.mTop - y) / (LLFontGL::getFontMonospace()->getLineHeight()+2) - 1; + S32 idx = (mLegendRect.mTop - y) / (LLFontGL::getFontMonospace()->getLineHeight() + 2); if (idx >= 0 && idx < (S32)ft_display_idx.size()) { @@ -208,26 +210,6 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) //left click drills down by expanding timers mHoverTimer->setCollapsed(false); } - else if (mask & MASK_ALT) - { - if (mask & MASK_CONTROL) - { - mDisplayHz = !mDisplayHz; - } - else - { - mDisplayCalls = !mDisplayCalls; - } - } - else if (mask & MASK_SHIFT) - { - if (++mDisplayMode > 3) - mDisplayMode = 0; - } - else if (mask & MASK_CONTROL) - { - mDisplayCenter = (ChildAlignment)((mDisplayCenter + 1) % ALIGN_COUNT); - } else if (mGraphRect.pointInRect(x, y)) { gFocusMgr.setMouseCapture(this); @@ -260,7 +242,10 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) if(mPauseHistory && mBarRect.pointInRect(x, y)) { - mHoverBarIndex = llmin((mBarRect.mTop - y) / (mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2)) - 1, + //const S32 bars_top = mBarRect.mTop; + const S32 bars_top = mBarRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4); + + mHoverBarIndex = llmin((bars_top - y) / (mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2)) - 1, (S32)mRecording.getNumRecordedPeriods() - 1, MAX_VISIBLE_HISTORY); if (mHoverBarIndex == 0) @@ -272,25 +257,33 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) mHoverBarIndex = 0; } - TimerBarRow& row = mHoverBarIndex == 0 ? mAverageTimerRow : mTimerBarRows[mHoverBarIndex - 1]; + TimerBarRow& row = mHoverBarIndex == 0 ? mAverageTimerRow : mTimerBarRows[mScrollIndex + mHoverBarIndex - 1]; TimerBar* hover_bar = NULL; LLUnit mouse_time_offset = ((F32)(x - mBarRect.mLeft) / (F32)mBarRect.getWidth()) * mTotalTimeDisplay; - for (std::vector::iterator it = row.mBars.begin(), end_it = row.mBars.end(); - it != end_it; - ++it) + for (int bar_index = 0, end_index = LLInstanceTracker::instanceCount(); + bar_index < end_index; + ++bar_index) { - if (it->mSelfStart > mouse_time_offset) + TimerBar& bar = row.mBars[bar_index]; + if (bar.mSelfStart > mouse_time_offset) { break; } - hover_bar = &(*it); + if (bar.mSelfEnd > mouse_time_offset) + { + hover_bar = &bar; + if (bar.mTimeBlock->getCollapsed()) + { + // stop on first collapsed timeblock, since we can't select any children + break; + } + } } if (hover_bar) { mHoverID = hover_bar->mTimeBlock; - mHoverTimer = mHoverID; if (mHoverTimer != mHoverID) { // could be that existing tooltip is for a parent and is thus @@ -300,7 +293,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) mHoverTimer = mHoverID; mToolTipRect.set(mBarRect.mLeft + (hover_bar->mSelfStart / mTotalTimeDisplay) * mBarRect.getWidth(), row.mTop, - mBarRect.mLeft + (hover_bar->mSelfStart / mTotalTimeDisplay) * mBarRect.getWidth(), + mBarRect.mLeft + (hover_bar->mSelfEnd / mTotalTimeDisplay) * mBarRect.getWidth(), row.mBottom); } } @@ -324,7 +317,7 @@ static std::string get_tooltip(TimeBlock& timer, S32 history_index, PeriodicReco if (history_index == 0) { // by default, show average number of call - tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit(frame_recording.getPeriodMean(timer)).value(), (S32)frame_recording.getPeriodMean(timer.callCount())); + tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit(frame_recording.getPeriodMean (timer, RUNNING_AVERAGE_WIDTH)).value(), (S32)frame_recording.getPeriodMean(timer.callCount(), RUNNING_AVERAGE_WIDTH)); } else { @@ -397,22 +390,34 @@ void LLFastTimerView::draw() mTimerBarRows.push_front(TimerBarRow()); } + mDisplayMode = llclamp(getChild("time_scale_combo")->getCurrentIndex(), 0, 3); + mDisplayType = (EDisplayType)llclamp(getChild("metric_combo")->getCurrentIndex(), 0, 2); + generateUniqueColors(); + LLView::drawChildren(); + //getChild("timer_bars_stack")->updateLayout(); + //getChild("legend_stack")->updateLayout(); + LLView* bars_panel = getChildView("bars_panel"); + bars_panel->localRectToOtherView(bars_panel->getLocalRect(), &mBarRect, this); + + LLView* lines_panel = getChildView("lines_panel"); + lines_panel->localRectToOtherView(lines_panel->getLocalRect(), &mGraphRect, this); + + LLView* legend_panel = getChildView("legend"); + legend_panel->localRectToOtherView(legend_panel->getLocalRect(), &mLegendRect, this); + // Draw the window background gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gl_rect_2d(getLocalRect(), LLColor4(0.f, 0.f, 0.f, 0.25f)); - S32 y = drawHelp(getRect().getHeight() - MARGIN); - drawLegend(y - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 2)); - - // update rectangle that includes timer bars - const S32 LEGEND_WIDTH = 220; + drawHelp(getRect().getHeight() - MARGIN); + drawLegend(); - mBarRect.mLeft = MARGIN + LEGEND_WIDTH + 8; - mBarRect.mTop = y; - mBarRect.mRight = getRect().getWidth() - MARGIN; - mBarRect.mBottom = MARGIN + LINE_GRAPH_HEIGHT; + //mBarRect.mLeft = MARGIN + LEGEND_WIDTH + 8; + //mBarRect.mTop = y; + //mBarRect.mRight = getRect().getWidth() - MARGIN; + //mBarRect.mBottom = MARGIN + LINE_GRAPH_HEIGHT; drawBars(); drawLineGraph(); @@ -433,7 +438,8 @@ void LLFastTimerView::onOpen(const LLSD& key) it != end_it; ++it) { - it->mBars.clear(); + delete []it->mBars; + it->mBars = NULL; } } @@ -993,7 +999,7 @@ void LLFastTimerView::printLineStats() LLUnit ticks; if (mStatsIndex == 0) { - ticks = mRecording.getPeriodMean(*idp); + ticks = mRecording.getPeriodMean(*idp, RUNNING_AVERAGE_WIDTH); } else { @@ -1019,8 +1025,6 @@ void LLFastTimerView::drawLineGraph() { LLFastTimer _(FTM_DRAW_LINE_GRAPH); //draw line graph history - S32 x = mBarRect.mLeft; - S32 y = LINE_GRAPH_HEIGHT; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLLocalClipRect clip(mGraphRect); @@ -1029,21 +1033,6 @@ void LLFastTimerView::drawLineGraph() static U32 max_calls = 0; static F32 alpha_interp = 0.f; - //display y-axis range - std::string axis_label; - if (mDisplayCalls) - axis_label = llformat("%d calls", (int)max_calls); - else if (mDisplayHz) - axis_label = llformat("%d Hz", (int)(1.f / max_time.value())); - else - axis_label = llformat("%4.2f ms", LLUnit(max_time).value()); - - x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(axis_label)-5; - y = mGraphRect.mTop - LLFontGL::getFontMonospace()->getLineHeight(); - - LLFontGL::getFontMonospace()->renderUTF8(axis_label, 0, x, y, LLColor4::white, - LLFontGL::LEFT, LLFontGL::TOP); - //highlight visible range { S32 first_frame = mRecording.getNumRecordedPeriods() - mScrollIndex; @@ -1059,7 +1048,7 @@ void LLFastTimerView::drawLineGraph() if (mHoverBarIndex > 0) { - S32 bar_frame = first_frame - mHoverBarIndex - 1; + S32 bar_frame = first_frame - (mScrollIndex + mHoverBarIndex) - 1; F32 bar = (F32) mGraphRect.mLeft + frame_delta*bar_frame; gGL.color4f(0.5f,0.5f,0.5f,1); @@ -1090,6 +1079,7 @@ void LLFastTimerView::drawLineGraph() const F32 * col = sTimerColors[idp->getIndex()].mV;// ft_display_table[idx].color->mV; F32 alpha = 1.f; + bool is_hover_timer = true; if (mHoverID != NULL && mHoverID != idp) @@ -1097,11 +1087,15 @@ void LLFastTimerView::drawLineGraph() if (idp->getParent() != mHoverID) { alpha = alpha_interp; + is_hover_timer = false; } } gGL.color4f(col[0], col[1], col[2], alpha); gGL.begin(LLRender::TRIANGLE_STRIP); + F32 call_scale_factor = (F32)mGraphRect.getHeight() / (F32)max_calls; + F32 time_scale_factor = (F32)mGraphRect.getHeight() / max_time.value(); + F32 hz_scale_factor = (F32) mGraphRect.getHeight() / (1.f / max_time.value()); for (U32 j = mRecording.getNumRecordedPeriods(); j > 0; j--) @@ -1110,16 +1104,26 @@ void LLFastTimerView::drawLineGraph() LLUnit time = llmax(recording.getSum(*idp), LLUnit(0.000001)); U32 calls = recording.getSum(idp->callCount()); - if (alpha == 1.f) + if (is_hover_timer) { //normalize to highlighted timer cur_max = llmax(cur_max, time); cur_max_calls = llmax(cur_max_calls, calls); } F32 x = mGraphRect.mRight - j * (F32)(mGraphRect.getWidth())/(mRecording.getNumRecordedPeriods()-1); - F32 y = mDisplayHz - ? mGraphRect.mBottom + (1.f / time.value()) * ((F32) mGraphRect.getHeight() / (1.f / max_time.value())) - : mGraphRect.mBottom + time / max_time * (F32)mGraphRect.getHeight(); + F32 y; + switch(mDisplayType) + { + case TIME: + y = mGraphRect.mBottom + time.value() * time_scale_factor; + break; + case CALLS: + y = mGraphRect.mBottom + (F32)calls * call_scale_factor; + break; + case HZ: + y = mGraphRect.mBottom + (1.f / time.value()) * hz_scale_factor; + break; + } gGL.vertex2f(x,y); gGL.vertex2f(x,mGraphRect.mBottom); } @@ -1140,7 +1144,7 @@ void LLFastTimerView::drawLineGraph() //interpolate towards new maximum max_time = lerp(max_time.value(), cur_max.value(), LLSmoothInterpolation::getInterpolant(0.1f)); - if (max_time - cur_max <= 1 || cur_max - max_time <= 1) + if (llabs((max_time - cur_max).value()) <= 1) { max_time = llmax(LLUnit(1), LLUnit(cur_max)); } @@ -1159,8 +1163,8 @@ void LLFastTimerView::drawLineGraph() if (mHoverID != NULL) { - x = (mGraphRect.mRight + mGraphRect.mLeft)/2; - y = mGraphRect.mBottom + 8; + S32 x = (mGraphRect.mRight + mGraphRect.mLeft)/2; + S32 y = mGraphRect.mBottom + 8; LLFontGL::getFontMonospace()->renderUTF8( mHoverID->getName(), @@ -1168,18 +1172,40 @@ void LLFastTimerView::drawLineGraph() x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM); - } + } + + //display y-axis range + std::string axis_label; + switch(mDisplayType) + { + case TIME: + axis_label = llformat("%4.2f ms", LLUnit(max_time).value()); + break; + case CALLS: + axis_label = llformat("%d calls", (int)max_calls); + break; + case HZ: + axis_label = llformat("%4.2f Hz", max_time.value() ? 1.f / max_time.value() : 0.f); + break; + } + + LLFontGL* font = LLFontGL::getFontMonospace(); + S32 x = mGraphRect.mRight - font->getWidth(axis_label)-5; + S32 y = mGraphRect.mTop - font->getLineHeight();; + + font->renderUTF8(axis_label, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); } -void LLFastTimerView::drawLegend( S32 y ) +void LLFastTimerView::drawLegend() { // draw legend S32 dx; - S32 x = MARGIN; + S32 x = mLegendRect.mLeft; + S32 y = mLegendRect.mTop; const S32 TEXT_HEIGHT = (S32)LLFontGL::getFontMonospace()->getLineHeight(); { - LLLocalClipRect clip(LLRect(MARGIN, y, LEGEND_WIDTH, MARGIN)); + LLLocalClipRect clip(mLegendRect); S32 cur_line = 0; ft_display_idx.clear(); std::map display_line; @@ -1214,18 +1240,22 @@ void LLFastTimerView::drawLegend( S32 y ) } else { - ms = LLUnit(mRecording.getPeriodMean(*idp)); - calls = (S32)mRecording.getPeriodMean(idp->callCount()); + ms = LLUnit(mRecording.getPeriodMean(*idp, RUNNING_AVERAGE_WIDTH)); + calls = (S32)mRecording.getPeriodMean(idp->callCount(), RUNNING_AVERAGE_WIDTH); } std::string timer_label; - if (mDisplayCalls) - { - timer_label = llformat("%s (%d)",idp->getName().c_str(),calls); - } - else + switch(mDisplayType) { + case TIME: timer_label = llformat("%s [%.1f]",idp->getName().c_str(),ms.value()); + break; + case CALLS: + timer_label = llformat("%s (%d)",idp->getName().c_str(),calls); + break; + case HZ: + timer_label = llformat("%.1f", ms.value() ? (1.f / ms.value()) : 0.f); + break; } dx = (TEXT_HEIGHT+4) + get_depth(idp)*8; @@ -1300,36 +1330,16 @@ void LLFastTimerView::generateUniqueColors() } } -S32 LLFastTimerView::drawHelp( S32 y ) +void LLFastTimerView::drawHelp( S32 y ) { // Draw some help const S32 texth = (S32)LLFontGL::getFontMonospace()->getLineHeight(); - char modedesc[][32] = { - "2 x Average ", - "Max ", - "Recent Max ", - "100 ms " - }; - char centerdesc[][32] = { - "Left ", - "Centered ", - "Ordered " - }; - - std::string text; - text = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, MARGIN, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - y -= (texth + 2); - text = llformat("Justification = %s [CTRL-Click to toggle]",centerdesc[mDisplayCenter]); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, MARGIN, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); y -= (texth + 2); - LLFontGL::getFontMonospace()->renderUTF8(std::string("[Right-Click log selected] [ALT-Click toggle counts] [ALT-SHIFT-Click sub hidden]"), + LLFontGL::getFontMonospace()->renderUTF8(std::string("[Right-Click log selected] [ALT-Click toggle counts]"), 0, MARGIN, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - y -= (texth + 2); - return y; } void LLFastTimerView::drawTicks() @@ -1392,7 +1402,7 @@ void LLFastTimerView::drawBorders( S32 y, const S32 x_start, S32 bar_height, S32 by = LINE_GRAPH_HEIGHT-dy; //line graph - mGraphRect = LLRect(x_start-5, by, getRect().getWidth()-5, 5); + //mGraphRect = LLRect(x_start-5, by, getRect().getWidth()-5, 5); gl_rect_2d(mGraphRect, FALSE); } @@ -1403,7 +1413,7 @@ void LLFastTimerView::updateTotalTime() switch(mDisplayMode) { case 0: - mTotalTimeDisplay = mRecording.getPeriodMean(FTM_FRAME, 100)*2; + mTotalTimeDisplay = mRecording.getPeriodMean(FTM_FRAME, RUNNING_AVERAGE_WIDTH)*2; break; case 1: mTotalTimeDisplay = mRecording.getPeriodMax(FTM_FRAME); @@ -1447,18 +1457,27 @@ void LLFastTimerView::drawBars() const S32 histmax = (S32)mRecording.getNumRecordedPeriods(); // update widths - updateTimerBarWidths(&FTM_FRAME, mAverageTimerRow, -1); - updateTimerBarOffsets(&FTM_FRAME, mAverageTimerRow); - - for (S32 history_index = 1; history_index <= histmax; history_index++) + if (!mPauseHistory) { - llassert(history_index <= mTimerBarRows.size()); - TimerBarRow& row = mTimerBarRows[history_index - 1]; - if (row.mBars.empty()) + U32 bar_index = 0; + if (!mAverageTimerRow.mBars) { - row.mBars.reserve(LLInstanceTracker::instanceCount()); - updateTimerBarWidths(&FTM_FRAME, row, history_index); - updateTimerBarOffsets(&FTM_FRAME, row); + mAverageTimerRow.mBars = new TimerBar[LLInstanceTracker::instanceCount()]; + } + updateTimerBarWidths(&FTM_FRAME, mAverageTimerRow, -1, bar_index); + updateTimerBarOffsets(&FTM_FRAME, mAverageTimerRow); + + for (S32 history_index = 1; history_index <= histmax; history_index++) + { + llassert(history_index <= mTimerBarRows.size()); + TimerBarRow& row = mTimerBarRows[history_index - 1]; + bar_index = 0; + if (!row.mBars) + { + row.mBars = new TimerBar[LLInstanceTracker::instanceCount()]; + updateTimerBarWidths(&FTM_FRAME, row, history_index, bar_index); + updateTimerBarOffsets(&FTM_FRAME, row); + } } } @@ -1492,32 +1511,28 @@ void LLFastTimerView::drawBars() static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_WIDTHS("Update timer bar widths"); -LLUnit LLFastTimerView::updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, bool visible) +LLUnit LLFastTimerView::updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, U32& bar_index) { LLFastTimer _(FTM_UPDATE_TIMER_BAR_WIDTHS); const LLUnit self_time = history_index == -1 - ? mRecording.getPeriodMean(time_block->selfTime()) + ? mRecording.getPeriodMean(time_block->selfTime(), RUNNING_AVERAGE_WIDTH) : mRecording.getPrevRecording(history_index).getSum(time_block->selfTime()); LLUnit full_time = self_time; // reserve a spot for this bar to be rendered before its children // even though we don't know its size yet - std::vector& bars = row.mBars; - S32 bar_index = bars.size(); - bars.push_back(TimerBar()); + TimerBar& timer_bar = row.mBars[bar_index]; + bar_index++; - const bool children_visible = visible && !time_block->getCollapsed(); for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); it != end_it; ++it) { - full_time += updateTimerBarWidths(*it, row, history_index, children_visible); + full_time += updateTimerBarWidths(*it, row, history_index, bar_index); } - TimerBar& timer_bar = bars[bar_index]; timer_bar.mTotalTime = full_time; timer_bar.mSelfTime = self_time; timer_bar.mTimeBlock = time_block; - timer_bar.mVisible = visible; return full_time; } @@ -1528,21 +1543,16 @@ S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, Timer { LLFastTimer _(FTM_UPDATE_TIMER_BAR_FRACTIONS); - std::vector& bars = row.mBars; - llassert(timer_bar_index < bars.size()); - TimerBar& timer_bar = bars[timer_bar_index]; - const LLUnit child_time_width = timer_bar.mTotalTime - timer_bar.mSelfTime; - timer_bar.mChildrenStart = timer_bar.mSelfStart; + TimerBar& timer_bar = row.mBars[timer_bar_index]; + const LLUnit bar_time = timer_bar.mTotalTime - timer_bar.mSelfTime; + timer_bar.mChildrenStart = timer_bar.mSelfStart + timer_bar.mSelfTime / 2; + timer_bar.mChildrenEnd = timer_bar.mChildrenStart + timer_bar.mTotalTime - timer_bar.mSelfTime; - if (mDisplayCenter == ALIGN_CENTER) + if (timer_bar_index == 0) { - timer_bar.mChildrenStart += timer_bar.mSelfTime / 2; + timer_bar.mSelfStart = 0.f; + timer_bar.mSelfEnd = bar_time; } - else if (mDisplayCenter == ALIGN_RIGHT) - { - timer_bar.mChildrenStart += timer_bar.mSelfTime; - } - timer_bar.mChildrenEnd = timer_bar.mChildrenStart + timer_bar.mTotalTime - timer_bar.mSelfTime; //now loop through children and figure out portion of bar image covered by each bar, now that we know the //sum of all children @@ -1556,8 +1566,7 @@ S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, Timer { timer_bar_index++; - llassert(timer_bar_index < bars.size()); - TimerBar& child_timer_bar = bars[timer_bar_index]; + TimerBar& child_timer_bar = row.mBars[timer_bar_index]; TimeBlock* child_time_block = *it; if (last_child_timer_bar) @@ -1574,15 +1583,15 @@ S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, Timer } child_timer_bar.mStartFraction = bar_fraction_start; - child_timer_bar.mEndFraction = child_time_width > 0 - ? bar_fraction_start + child_timer_bar.mTotalTime / child_time_width + child_timer_bar.mEndFraction = bar_time > 0 + ? bar_fraction_start + child_timer_bar.mTotalTime / bar_time : 1.f; - child_timer_bar.mSelfStart = timer_bar.mChildrenStart - + child_timer_bar.mStartFraction - * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart); - child_timer_bar.mSelfEnd = timer_bar.mChildrenStart - + child_timer_bar.mEndFraction - * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart); + child_timer_bar.mSelfStart = timer_bar.mChildrenStart + + child_timer_bar.mStartFraction + * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart); + child_timer_bar.mSelfEnd = timer_bar.mChildrenStart + + child_timer_bar.mEndFraction + * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart); timer_bar_index = updateTimerBarOffsets(child_time_block, row, timer_bar_index); @@ -1591,16 +1600,15 @@ S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, Timer return timer_bar_index; } -S32 LLFastTimerView::drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, S32 bar_index) +S32 LLFastTimerView::drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, bool visible, S32 bar_index) { - llassert(bar_index < row.mBars.size()); TimerBar& timer_bar = row.mBars[bar_index]; LLTrace::TimeBlock* time_block = timer_bar.mTimeBlock; hovered |= mHoverID == time_block; // animate scale of bar when hovering over that particular timer - if ((F32)bar_rect.getWidth() * (timer_bar.mEndFraction - timer_bar.mStartFraction) > 2.f) + if (visible && (F32)bar_rect.getWidth() * (timer_bar.mEndFraction - timer_bar.mStartFraction) > 2.f) { LLRect render_rect(bar_rect); S32 scale_offset = 0; @@ -1637,15 +1645,17 @@ S32 LLFastTimerView::drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, children_rect.mBottom = bar_rect.mBottom; } + bool children_visible = visible && !time_block->getCollapsed(); + bar_index++; - const U32 num_bars = row.mBars.size(); + const U32 num_bars = LLInstanceTracker::instanceCount(); if (bar_index < num_bars && row.mBars[bar_index].mFirstChild) { bool is_last = false; do { is_last = row.mBars[bar_index].mLastChild; - bar_index = drawBar(children_rect, row, image_width, image_height, hovered, bar_index); + bar_index = drawBar(children_rect, row, image_width, image_height, hovered, children_visible, bar_index); } while(!is_last && bar_index < num_bars); } diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index d9ae6348da..d931f25a7e 100755 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -68,8 +68,8 @@ private: virtual void onClickCloseBtn(); void drawTicks(); void drawLineGraph(); - void drawLegend(S32 y); - S32 drawHelp(S32 y); + void drawLegend(); + void drawHelp(S32 y); void drawBorders( S32 y, const S32 x_start, S32 barh, S32 dy); void drawBars(); @@ -82,7 +82,6 @@ private: TimerBar() : mTotalTime(0), mSelfTime(0), - mVisible(true), mStartFraction(0.f), mEndFraction(1.f), mFirstChild(false), @@ -104,29 +103,26 @@ private: struct TimerBarRow { - S32 mBottom, - mTop; - std::vector mBars; + S32 mBottom, + mTop; + TimerBar* mBars; }; - LLUnit updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, bool visible = true); + LLUnit updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, U32& bar_index); S32 updateTimerBarOffsets(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 timer_bar_index = 0); - S32 drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered = false, S32 bar_index = 0); + S32 drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered = false, bool visible = true, S32 bar_index = 0); void setPauseState(bool pause_state); std::deque mTimerBarRows; TimerBarRow mAverageTimerRow; - enum ChildAlignment + enum EDisplayType { - ALIGN_LEFT, - ALIGN_CENTER, - ALIGN_RIGHT, - ALIGN_COUNT - } mDisplayCenter; - bool mDisplayCalls, - mDisplayHz, - mPauseHistory; + TIME, + CALLS, + HZ + } mDisplayType; + bool mPauseHistory; LLUnit mAllTimeMax, mTotalTimeDisplay; S32 mScrollIndex, @@ -137,7 +133,8 @@ private: LLTrace::TimeBlock* mHoverTimer; LLRect mToolTipRect, mGraphRect, - mBarRect; + mBarRect, + mLegendRect; LLFrameTimer mHighlightTimer; LLTrace::PeriodicRecording mRecording; }; diff --git a/indra/newview/skins/default/xui/en/floater_fast_timers.xml b/indra/newview/skins/default/xui/en/floater_fast_timers.xml index 77adb5524e..671f116df3 100755 --- a/indra/newview/skins/default/xui/en/floater_fast_timers.xml +++ b/indra/newview/skins/default/xui/en/floater_fast_timers.xml @@ -16,6 +16,27 @@ width="700"> Pause Run + + + + + + + + + + +