diff options
Diffstat (limited to 'indra')
40 files changed, 1157 insertions, 916 deletions
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<LLUnits::Milliseconds, F32>(100)); + mRoll = LLSmoothInterpolation::lerp(mRoll, target_roll, LLUnit<F32, LLUnits::Milliseconds>(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<LLUnits::Seconds, F32> time_constant, bool use_cache) +F32 LLSmoothInterpolation::getInterpolant(LLUnit<F32, LLUnits::Seconds> 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<LLUnits::Seconds, F32> time_constant, bool use_cache = true); + static F32 getInterpolant(LLUnit<F32, LLUnits::Seconds> time_constant, bool use_cache = true); template<typename T> - static T lerp(T a, T b, LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache = true) + static T lerp(T a, T b, LLUnit<F32, LLUnits::Seconds> 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<LLUnits::Seconds, F64> seconds_since_epoch) : +LLDate::LLDate(LLUnit<F64, LLUnits::Seconds> 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<LLUnits::Seconds, F64> seconds_since_epoch); + LLDate(LLUnit<F64, LLUnits::Seconds> 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..becfa9c288 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -118,7 +118,7 @@ struct SortTimerByName TimeBlock& TimeBlock::getRootTimeBlock() { - static TimeBlock root_timer("root", true, NULL); + static TimeBlock root_timer("root", NULL); return root_timer; } @@ -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<LLUnits::Hertz, U64> sCPUClockFrequency = LLProcessorInfo().getCPUFrequency(); - + static LLUnit<U64, LLUnits::Hertz> 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,16 +159,14 @@ U64 TimeBlock::countsPerSecond() QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency); firstcall = false; } -#endif return sCPUClockFrequency.value(); +#endif } #endif -TimeBlock::TimeBlock(const char* name, bool open, TimeBlock* parent) -: TraceType<TimeBlockAccumulator>(name), - mCollapsed(true) +TimeBlock::TimeBlock(const char* name, TimeBlock* parent) +: TraceType<TimeBlockAccumulator>(name) { - setCollapsed(!open); } TimeBlockTreeNode& TimeBlock::getTreeNode() const @@ -178,43 +176,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<TimeBlock>::instance_iter begin_it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::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 +233,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 +269,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<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), @@ -288,14 +306,13 @@ void TimeBlock::processTimes() } } - std::vector<TimeBlock*>::iterator TimeBlock::beginChildren() - { +{ return getTreeNode().mChildren.begin(); - } +} std::vector<TimeBlock*>::iterator TimeBlock::endChildren() - { +{ return getTreeNode().mChildren.end(); } @@ -318,11 +335,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<LLUnits::Hertz, F64>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL; + LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64()) / (LLUnit<F64, LLUnits::Hertz>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL; } call_count++; - LLUnit<LLUnits::Seconds, F64> total_time(0); + LLUnit<F64, LLUnits::Seconds> total_time(0); LLSD sd; { @@ -365,11 +382,11 @@ void TimeBlock::dumpCurTimes() ++it) { TimeBlock* timerp = (*it); - LLUnit<LLUnits::Seconds, F64> total_time_ms = last_frame_recording.getSum(*timerp); + LLUnit<F64, LLUnits::Seconds> 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<F32, LLUnits::Milliseconds>(0.1)) continue; std::ostringstream out_str; TimeBlock* parent_timerp = timerp; @@ -380,7 +397,7 @@ void TimeBlock::dumpCurTimes() } out_str << timerp->getName() << " " - << std::setprecision(3) << total_time_ms.as<LLUnits::Milliseconds>().value() << " ms, " + << std::setprecision(3) << total_time.getAs<LLUnits::Milliseconds>() << " ms, " << num_calls << " calls"; llinfos << out_str.str() << llendl; @@ -449,7 +466,7 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other ) } } -LLUnit<LLUnits::Seconds, F64> BlockTimer::getElapsedTime() +LLUnit<F64, LLUnits::Seconds> BlockTimer::getElapsedTime() { U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime; diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 20514d1638..642c99ccce 100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -71,7 +71,7 @@ public: BlockTimer(TimeBlock& timer); ~BlockTimer(); - LLUnit<LLUnits::Seconds, F64> getElapsedTime(); + LLUnit<F64, LLUnits::Seconds> getElapsedTime(); private: @@ -86,7 +86,7 @@ class TimeBlock public LLInstanceTracker<TimeBlock> { public: - TimeBlock(const char* name, bool open = false, TimeBlock* parent = &getRootTimeBlock()); + TimeBlock(const char* name, TimeBlock* parent = &getRootTimeBlock()); TimeBlockTreeNode& getTreeNode() const; TimeBlock* getParent() const { return getTreeNode().getParent(); } @@ -98,9 +98,6 @@ public: child_iter endChildren(); std::vector<TimeBlock*>& getChildren(); - void setCollapsed(bool collapsed) { mCollapsed = collapsed; } - bool getCollapsed() const { return mCollapsed; } - TraceType<TimeBlockAccumulator::CallCountFacet>& callCount() { return static_cast<TraceType<TimeBlockAccumulator::CallCountFacet>&>(*(TraceType<TimeBlockAccumulator>*)this); @@ -115,6 +112,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 +260,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/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<LLUnits::Megahertz, F64> LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +LLUnitImplicit<F64, LLUnits::Megahertz> 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<LLUnits::Megahertz, F64> getCPUFrequency() const; + LLUnitImplicit<F64, LLUnits::Megahertz> 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<LLUnits::Microseconds, U64> LLTimer::getTotalTime() +LLUnitImplicit<U64, LLUnits::Microseconds> LLTimer::getTotalTime() { // simply call into the implementation function. return totalTime(); } // static -LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getTotalSeconds() +LLUnitImplicit<F64, LLUnits::Seconds> LLTimer::getTotalSeconds() { return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64; } @@ -341,23 +341,23 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount) } -LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeF64() const +LLUnitImplicit<F64, LLUnits::Seconds> LLTimer::getElapsedTimeF64() const { U64 last = mLastClockCount; return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv; } -LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeF32() const +LLUnitImplicit<F32, LLUnits::Seconds> LLTimer::getElapsedTimeF32() const { return (F32)getElapsedTimeF64(); } -LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeAndResetF64() +LLUnitImplicit<F64, LLUnits::Seconds> LLTimer::getElapsedTimeAndResetF64() { return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv; } -LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeAndResetF32() +LLUnitImplicit<F32, LLUnits::Seconds> LLTimer::getElapsedTimeAndResetF32() { return (F32)getElapsedTimeAndResetF64(); } @@ -370,7 +370,7 @@ void LLTimer::setTimerExpirySec(F32 expiration) + (U64)((F32)(expiration * gClockFrequency)); } -LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getRemainingTimeF32() const +LLUnitImplicit<F32, LLUnits::Seconds> 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<LLUnits::Seconds, F64> getElapsedSeconds() + static LLUnitImplicit<F64, LLUnits::Seconds> getElapsedSeconds() { return sTimer->getElapsedTimeF64(); } // Return a high precision usec since epoch - static LLUnitImplicit<LLUnits::Microseconds, U64> getTotalTime(); + static LLUnitImplicit<U64, LLUnits::Microseconds> getTotalTime(); // Return a high precision seconds since epoch - static LLUnitImplicit<LLUnits::Seconds, F64> getTotalSeconds(); + static LLUnitImplicit<F64, LLUnits::Seconds> getTotalSeconds(); // MANIPULATORS @@ -87,16 +87,16 @@ public: void setTimerExpirySec(F32 expiration); BOOL checkExpirationAndReset(F32 expiration); BOOL hasExpired() const; - LLUnitImplicit<LLUnits::Seconds, F32> getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset - LLUnitImplicit<LLUnits::Seconds, F64> getElapsedTimeAndResetF64(); + LLUnitImplicit<F32, LLUnits::Seconds> getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset + LLUnitImplicit<F64, LLUnits::Seconds> getElapsedTimeAndResetF64(); - LLUnitImplicit<LLUnits::Seconds, F32> getRemainingTimeF32() const; + LLUnitImplicit<F32, LLUnits::Seconds> getRemainingTimeF32() const; static BOOL knownBadTimer(); // ACCESSORS - LLUnitImplicit<LLUnits::Seconds, F32> getElapsedTimeF32() const; // Returns elapsed time in seconds - LLUnitImplicit<LLUnits::Seconds, F64> getElapsedTimeF64() const; // Returns elapsed time in seconds + LLUnitImplicit<F32, LLUnits::Seconds> getElapsedTimeF32() const; // Returns elapsed time in seconds + LLUnitImplicit<F64, LLUnits::Seconds> getElapsedTimeF64() const; // Returns elapsed time in seconds bool getStarted() const { return mStarted; } diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp index c831a1548d..59a4b42c97 100644 --- a/indra/llcommon/lltrace.cpp +++ b/indra/llcommon/lltrace.cpp @@ -85,7 +85,8 @@ void set_thread_recorder(ThreadRecorder* recorder) TimeBlockTreeNode::TimeBlockTreeNode() : mBlock(NULL), mParent(NULL), - mNeedsSorting(false) + mNeedsSorting(false), + mCollapsed(true) {} void TimeBlockTreeNode::setParent( TimeBlock* parent ) diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index cfe1273b4b..fb7ffb0a29 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -44,27 +44,37 @@ namespace LLTrace { class Recording; -typedef LLUnit<LLUnits::Bytes, F64> Bytes; -typedef LLUnit<LLUnits::Kibibytes, F64> Kibibytes; -typedef LLUnit<LLUnits::Mibibytes, F64> Mibibytes; -typedef LLUnit<LLUnits::Gibibytes, F64> Gibibytes; -typedef LLUnit<LLUnits::Bits, F64> Bits; -typedef LLUnit<LLUnits::Kibibits, F64> Kibibits; -typedef LLUnit<LLUnits::Mibibits, F64> Mibibits; -typedef LLUnit<LLUnits::Gibibits, F64> Gibibits; - -typedef LLUnit<LLUnits::Seconds, F64> Seconds; -typedef LLUnit<LLUnits::Milliseconds, F64> Milliseconds; -typedef LLUnit<LLUnits::Minutes, F64> Minutes; -typedef LLUnit<LLUnits::Hours, F64> Hours; -typedef LLUnit<LLUnits::Milliseconds, F64> Milliseconds; -typedef LLUnit<LLUnits::Microseconds, F64> Microseconds; -typedef LLUnit<LLUnits::Nanoseconds, F64> Nanoseconds; - -typedef LLUnit<LLUnits::Meters, F64> Meters; -typedef LLUnit<LLUnits::Kilometers, F64> Kilometers; -typedef LLUnit<LLUnits::Centimeters, F64> Centimeters; -typedef LLUnit<LLUnits::Millimeters, F64> Millimeters; +typedef LLUnit<F64, LLUnits::Bytes> Bytes; +typedef LLUnit<F64, LLUnits::Kibibytes> Kibibytes; +typedef LLUnit<F64, LLUnits::Mibibytes> Mibibytes; +typedef LLUnit<F64, LLUnits::Gibibytes> Gibibytes; +typedef LLUnit<F64, LLUnits::Bits> Bits; +typedef LLUnit<F64, LLUnits::Kibibits> Kibibits; +typedef LLUnit<F64, LLUnits::Mibibits> Mibibits; +typedef LLUnit<F64, LLUnits::Gibibits> Gibibits; + +typedef LLUnit<F64, LLUnits::Seconds> Seconds; +typedef LLUnit<F64, LLUnits::Milliseconds> Milliseconds; +typedef LLUnit<F64, LLUnits::Minutes> Minutes; +typedef LLUnit<F64, LLUnits::Hours> Hours; +typedef LLUnit<F64, LLUnits::Milliseconds> Milliseconds; +typedef LLUnit<F64, LLUnits::Microseconds> Microseconds; +typedef LLUnit<F64, LLUnits::Nanoseconds> Nanoseconds; + +typedef LLUnit<F64, LLUnits::Meters> Meters; +typedef LLUnit<F64, LLUnits::Kilometers> Kilometers; +typedef LLUnit<F64, LLUnits::Centimeters> Centimeters; +typedef LLUnit<F64, LLUnits::Millimeters> Millimeters; + + +template<typename T> +T storage_value(T val) { return val; } + +template<typename UNIT_TYPE, typename STORAGE_TYPE> +STORAGE_TYPE storage_value(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); } + +template<typename UNIT_TYPE, typename STORAGE_TYPE> +STORAGE_TYPE storage_value(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); } void init(); void cleanup(); @@ -147,12 +157,12 @@ public: } } - void flush() + void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) { llassert(mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { - mStorage[i].flush(); + mStorage[i].flush(time_stamp); } } @@ -217,6 +227,11 @@ public: size_t size() const { + return getNumIndices(); + } + + static size_t getNumIndices() + { return sNextStorageSlot; } @@ -263,6 +278,7 @@ public: } size_t getIndex() const { return mAccumulatorIndex; } + static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); } virtual const char* getUnitLabel() { return ""; } @@ -364,7 +380,7 @@ public: mLastValue = other ? other->mLastValue : 0; } - void flush() {} + void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {} F64 getSum() const { return mSum; } F64 getMin() const { return mMin; } @@ -408,8 +424,8 @@ public: void sample(F64 value) { - LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds(); - LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp; + LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds(); + LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp; mLastSampleTimeStamp = time_stamp; if (mHasValue) @@ -496,10 +512,9 @@ public: mHasValue = other ? other->mHasValue : false; } - void flush() + void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) { - LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds(); - LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp; + LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp; if (mHasValue) { @@ -528,7 +543,7 @@ private: F64 mMean, mVarianceSum; - LLUnitImplicit<LLUnits::Seconds, F64> mLastSampleTimeStamp, + LLUnitImplicit<F64, LLUnits::Seconds> mLastSampleTimeStamp, mTotalSamplingTime; U32 mNumSamples; @@ -563,7 +578,7 @@ public: mSum = 0; } - void flush() {} + void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {} F64 getSum() const { return mSum; } @@ -578,8 +593,8 @@ private: class TimeBlockAccumulator { public: - typedef LLUnit<LLUnits::Seconds, F64> value_t; - typedef LLUnit<LLUnits::Seconds, F64> mean_t; + typedef LLUnit<F64, LLUnits::Seconds> value_t; + typedef LLUnit<F64, LLUnits::Seconds> mean_t; typedef TimeBlockAccumulator self_t; // fake classes that allows us to view different facets of underlying statistic @@ -591,14 +606,14 @@ public: struct SelfTimeFacet { - typedef LLUnit<LLUnits::Seconds, F64> value_t; - typedef LLUnit<LLUnits::Seconds, F64> mean_t; + typedef LLUnit<F64, LLUnits::Seconds> value_t; + typedef LLUnit<F64, LLUnits::Seconds> mean_t; }; TimeBlockAccumulator(); void addSamples(const self_t& other, bool /*append*/); void reset(const self_t* other); - void flush() {} + void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {} // // members @@ -648,6 +663,7 @@ public: TimeBlock* mBlock; TimeBlock* mParent; std::vector<TimeBlock*> mChildren; + bool mCollapsed; bool mNeedsSorting; }; @@ -672,7 +688,7 @@ template<typename T, typename VALUE_T> void record(EventStatHandle<T>& measurement, VALUE_T value) { T converted_value(value); - measurement.getPrimaryAccumulator()->record(LLUnits::rawValue(converted_value)); + measurement.getPrimaryAccumulator()->record(storage_value(converted_value)); } template <typename T = F64> @@ -694,7 +710,7 @@ template<typename T, typename VALUE_T> void sample(SampleStatHandle<T>& measurement, VALUE_T value) { T converted_value(value); - measurement.getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value)); + measurement.getPrimaryAccumulator()->sample(storage_value(converted_value)); } template <typename T = F64> @@ -716,7 +732,7 @@ template<typename T, typename VALUE_T> void add(CountStatHandle<T>& count, VALUE_T value) { T converted_value(value); - count.getPrimaryAccumulator()->add(LLUnits::rawValue(converted_value)); + count.getPrimaryAccumulator()->add(storage_value(converted_value)); } @@ -739,8 +755,8 @@ struct MemStatAccumulator struct ChildMemFacet { - typedef LLUnit<LLUnits::Bytes, F64> value_t; - typedef LLUnit<LLUnits::Bytes, F64> mean_t; + typedef LLUnit<F64, LLUnits::Bytes> value_t; + typedef LLUnit<F64, LLUnits::Bytes> mean_t; }; MemStatAccumulator() @@ -764,10 +780,10 @@ struct MemStatAccumulator mDeallocatedCount = 0; } - void flush() + void flush(LLUnitImplicit<F64, LLUnits::Seconds> 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 d32504b014..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<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds(); + + mSamples.flush(time_stamp); } /////////////////////////////////////////////////////////////////////// @@ -122,21 +124,26 @@ 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<Recording&>(other); + mutable_other.update(); EPlayState other_play_state = other.getPlayState(); - mutable_other.pause(); - mBuffers = other.mBuffers; + mBuffers = mutable_other.mBuffers; LLStopWatchControlsMixin<Recording>::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; } @@ -186,240 +193,198 @@ 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<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) +LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; - update(); return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond(); } -LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat) +LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; - update(); return (F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond(); } U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat) { - update(); return mBuffers->mStackTimers[stat.getIndex()].mCalls; } -LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) +LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& 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<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat) +LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& 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<TimeBlockAccumulator::CallCountFacet>& stat) { - update(); - return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds; + return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMin(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMin(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMean(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMean(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMax(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMax(); } -LLUnit<LLUnits::Bytes, F64> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation(); } -LLUnit<LLUnits::Bytes, F64> Recording::getLastValue(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax(); } -LLUnit<LLUnits::Bytes, F64> Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation(); } -LLUnit<LLUnits::Bytes, F64> Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue(); } U32 Recording::getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount; } U32 Recording::getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount; } F64 Recording::getSum( const TraceType<CountAccumulator>& stat ) { - update(); return mBuffers->mCounts[stat.getIndex()].getSum(); } F64 Recording::getSum( const TraceType<EventAccumulator>& stat ) { - update(); return (F64)mBuffers->mEvents[stat.getIndex()].getSum(); } F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat ) { - update(); F64 sum = mBuffers->mCounts[stat.getIndex()].getSum(); return (sum != 0.0) - ? (sum / mElapsedSeconds) + ? (sum / mElapsedSeconds.value()) : 0.0; } U32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat ) { - update(); return mBuffers->mCounts[stat.getIndex()].getSampleCount(); } F64 Recording::getMin( const TraceType<SampleAccumulator>& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getMin(); } F64 Recording::getMax( const TraceType<SampleAccumulator>& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getMax(); } F64 Recording::getMean( const TraceType<SampleAccumulator>& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getMean(); } F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator>& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getStandardDeviation(); } F64 Recording::getLastValue( const TraceType<SampleAccumulator>& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getLastValue(); } U32 Recording::getSampleCount( const TraceType<SampleAccumulator>& stat ) { - update(); return mBuffers->mSamples[stat.getIndex()].getSampleCount(); } F64 Recording::getMin( const TraceType<EventAccumulator>& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getMin(); } F64 Recording::getMax( const TraceType<EventAccumulator>& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getMax(); } F64 Recording::getMean( const TraceType<EventAccumulator>& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getMean(); } F64 Recording::getStandardDeviation( const TraceType<EventAccumulator>& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getStandardDeviation(); } F64 Recording::getLastValue( const TraceType<EventAccumulator>& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getLastValue(); } U32 Recording::getSampleCount( const TraceType<EventAccumulator>& stat ) { - update(); return mBuffers->mEvents[stat.getIndex()].getSampleCount(); } @@ -430,6 +395,7 @@ U32 Recording::getSampleCount( const TraceType<EventAccumulator>& 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 +409,16 @@ 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) +{ + getCurRecording().appendRecording(recording); + nextPeriod(); } @@ -453,77 +426,71 @@ 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()) + if (mAutoResize) { - nextPeriod(); - } - getCurRecording().appendRecording(other_oldest_recording); + S32 other_index = (other.mCurPeriod + 1) % other.mRecordingPeriods.size(); + S32 end_index = (other.mCurPeriod) % other.mRecordingPeriods.size(); - if (other_recording_count > 1) - { - if (mAutoResize) + 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<Recording>::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<Recording>::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<Recording>::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<Recording>::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<LLUnits::Seconds, F64> PeriodicRecording::getDuration() const +LLUnit<F64, LLUnits::Seconds> PeriodicRecording::getDuration() const { - LLUnit<LLUnits::Seconds, F64> duration; + LLUnit<F64, LLUnits::Seconds> duration; size_t num_periods = mRecordingPeriods.size(); for (size_t i = 1; i <= num_periods; i++) { @@ -615,7 +582,7 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other) F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& 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 +610,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, s F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& 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<F64>::max(); for (S32 i = 1; i <= num_periods; i++) @@ -657,7 +624,7 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, si F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& 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<F64>::min(); for (S32 i = 1; i <= num_periods; i++) @@ -671,7 +638,7 @@ F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, si F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& 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<F64>::max(); for (S32 i = 1; i <= num_periods; i++) @@ -685,7 +652,7 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, s F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& 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<F64>::min(); for (S32 i = 1; i <= num_periods; i++) @@ -700,9 +667,9 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, si F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& 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<LLUnits::Seconds, F64> total_duration = 0.f; + LLUnit<F64, LLUnits::Seconds> total_duration = 0.f; F64 mean = 0; if (num_periods <= 0) { return mean; } @@ -712,7 +679,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat, S32 index = (mCurPeriod + total_periods - i) % total_periods; if (mRecordingPeriods[index].getDuration() > 0.f) { - LLUnit<LLUnits::Seconds, F64> recording_duration = mRecordingPeriods[index].getDuration(); + LLUnit<F64, LLUnits::Seconds> recording_duration = mRecordingPeriods[index].getDuration(); mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value(); total_duration += recording_duration; } @@ -734,13 +701,11 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& 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 +742,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..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); @@ -148,26 +150,26 @@ namespace LLTrace void makeUnique() { mBuffers.makeUnique(); } // Timer accessors - LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat); - LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); + LLUnit<F64, LLUnits::Seconds> getSum(const TraceType<TimeBlockAccumulator>& stat); + LLUnit<F64, LLUnits::Seconds> getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); U32 getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat); - LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator>& stat); - LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); + LLUnit<F64, LLUnits::Seconds> getPerSec(const TraceType<TimeBlockAccumulator>& stat); + LLUnit<F64, LLUnits::Seconds> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat); // Memory accessors - LLUnit<LLUnits::Bytes, F64> getMin(const TraceType<MemStatAccumulator>& stat); - LLUnit<LLUnits::Bytes, F64> getMean(const TraceType<MemStatAccumulator>& stat); - LLUnit<LLUnits::Bytes, F64> getMax(const TraceType<MemStatAccumulator>& stat); - LLUnit<LLUnits::Bytes, F64> getStandardDeviation(const TraceType<MemStatAccumulator>& stat); - LLUnit<LLUnits::Bytes, F64> getLastValue(const TraceType<MemStatAccumulator>& stat); - - LLUnit<LLUnits::Bytes, F64> getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); - LLUnit<LLUnits::Bytes, F64> getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); - LLUnit<LLUnits::Bytes, F64> getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); - LLUnit<LLUnits::Bytes, F64> getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); - LLUnit<LLUnits::Bytes, F64> getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getMin(const TraceType<MemStatAccumulator>& stat); + LLUnit<F64, LLUnits::Bytes> getMean(const TraceType<MemStatAccumulator>& stat); + LLUnit<F64, LLUnits::Bytes> getMax(const TraceType<MemStatAccumulator>& stat); + LLUnit<F64, LLUnits::Bytes> getStandardDeviation(const TraceType<MemStatAccumulator>& stat); + LLUnit<F64, LLUnits::Bytes> getLastValue(const TraceType<MemStatAccumulator>& stat); + + LLUnit<F64, LLUnits::Bytes> getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); U32 getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat); U32 getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat); @@ -273,7 +275,7 @@ namespace LLTrace U32 getSampleCount(const TraceType<EventAccumulator>& stat); - LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); } + LLUnit<F64, LLUnits::Seconds> getDuration() const { return mElapsedSeconds; } protected: friend class ThreadRecorder; @@ -288,7 +290,7 @@ namespace LLTrace class ThreadRecorder* getThreadRecorder(); LLTimer mSamplingTimer; - F64 mElapsedSeconds; + LLUnit<F64, LLUnits::Seconds> mElapsedSeconds; LLCopyOnWritePointer<RecordingBuffers> mBuffers; }; @@ -299,11 +301,12 @@ namespace LLTrace PeriodicRecording(U32 num_periods, EPlayState state = STOPPED); void nextPeriod(); - U32 getNumPeriods() { return mRecordingPeriods.size(); } + size_t getNumRecordedPeriods() { return mNumPeriods; } - LLUnit<LLUnits::Seconds, F64> getDuration() const; + LLUnit<F64, LLUnits::Seconds> getDuration() const; void appendPeriodicRecording(PeriodicRecording& other); + void appendRecording(Recording& recording); Recording& getLastRecording(); const Recording& getLastRecording() const; Recording& getCurRecording(); @@ -317,7 +320,7 @@ namespace LLTrace typename T::value_t getPeriodMin(const TraceType<T>& 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<typename T::value_t>::max(); for (S32 i = 1; i <= num_periods; i++) @@ -346,7 +349,7 @@ namespace LLTrace F64 getPeriodMinPerSec(const TraceType<T>& 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<F64>::max(); for (S32 i = 1; i <= num_periods; i++) @@ -362,7 +365,7 @@ namespace LLTrace typename T::value_t getPeriodMax(const TraceType<T>& 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<typename T::value_t>::min(); for (S32 i = 1; i <= num_periods; i++) @@ -391,7 +394,7 @@ namespace LLTrace F64 getPeriodMaxPerSec(const TraceType<T>& 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<F64>::min(); for (S32 i = 1; i <= num_periods; i++) @@ -407,7 +410,7 @@ namespace LLTrace typename T::mean_t getPeriodMean(const TraceType<T >& 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 +445,7 @@ namespace LLTrace typename T::mean_t getPeriodMeanPerSec(const TraceType<T>& 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 +471,9 @@ namespace LLTrace private: std::vector<Recording> mRecordingPeriods; - const bool mAutoResize; - S32 mCurPeriod; + const bool mAutoResize; + size_t mCurPeriod; + size_t mNumPeriods; }; PeriodicRecording& get_frame_recording(); 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/llunit.h b/indra/llcommon/llunit.h index f48cbe0e11..5229fe69d7 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -30,36 +30,12 @@ #include "stdtypes.h" #include "llpreprocessor.h" #include "llerrorlegacy.h" +#include <boost/type_traits/is_same.hpp> -namespace LLUnits -{ - -template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG, typename VALUE_TYPE> -struct ConversionFactor -{ - static F64 get() - { - // 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; - } -}; - -template<typename BASE_UNITS_TAG, typename VALUE_TYPE> -struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE> -{ - static F64 get() - { - return 1; - } -}; - -} - -template<typename UNIT_TYPE, typename STORAGE_TYPE> +template<typename STORAGE_TYPE, typename UNIT_TYPE> struct LLUnit { - typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t; + typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t; typedef STORAGE_TYPE storage_t; // value initialization @@ -68,11 +44,16 @@ struct LLUnit {} // unit initialization and conversion - template<typename OTHER_UNIT, typename OTHER_STORAGE> - LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other) - : mValue(convert(other)) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other) + : mValue(convert(other).mValue) {} + bool operator == (const self_t& other) + { + return mValue = other.mValue; + } + // value assignment self_t& operator = (storage_t value) { @@ -81,10 +62,10 @@ struct LLUnit } // unit assignment - template<typename OTHER_UNIT, typename OTHER_STORAGE> - self_t& operator = (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + self_t& operator = (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) { - mValue = convert(other); + mValue = convert(other).mValue; return *this; } @@ -93,21 +74,27 @@ struct LLUnit return mValue; } - template<typename NEW_UNIT_TYPE> LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE> as() + template<typename NEW_UNIT_TYPE> + STORAGE_TYPE getAs() { - return LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE>(*this); + return LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(*this).value(); } + template<typename NEW_UNIT_TYPE> + STORAGE_TYPE setAs(STORAGE_TYPE val) + { + *this = LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(val); + } void operator += (storage_t value) { mValue += value; } - template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator += (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + void operator += (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) { - mValue += convert(other); + mValue += convert(other).mValue; } void operator -= (storage_t value) @@ -115,10 +102,10 @@ struct LLUnit mValue -= value; } - template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator -= (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + void operator -= (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) { - mValue -= convert(other); + mValue -= convert(other).mValue; } void operator *= (storage_t multiplicand) @@ -127,7 +114,7 @@ struct LLUnit } template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator *= (LLUnit<OTHER_UNIT, OTHER_STORAGE> multiplicand) + void operator *= (LLUnit<OTHER_STORAGE, OTHER_UNIT> 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 +126,37 @@ struct LLUnit } template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor) + void operator /= (LLUnit<OTHER_STORAGE, OTHER_UNIT> 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<typename SOURCE_UNITS, typename SOURCE_STORAGE> - static storage_t convert(LLUnit<SOURCE_UNITS, SOURCE_STORAGE> v) + template<typename SOURCE_STORAGE, typename SOURCE_UNITS> + static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) { - return (storage_t)(v.value() - * LLUnits::ConversionFactor<SOURCE_UNITS, typename UNIT_TYPE::base_unit_t, SOURCE_STORAGE>::get() - * LLUnits::ConversionFactor<typename UNIT_TYPE::base_unit_t, UNIT_TYPE, STORAGE_TYPE>::get()); + self_t result; + ll_convert_units(v, result); + return result; } protected: storage_t mValue; }; -template<typename UNIT_TYPE, typename STORAGE_TYPE> -struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE> +template<typename STORAGE_TYPE, typename UNIT_TYPE> +struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE> { - typedef LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> self_t; - typedef typename LLUnit<UNIT_TYPE, STORAGE_TYPE>::storage_t storage_t; - typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> base_t; + typedef LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> self_t; + typedef typename LLUnit<STORAGE_TYPE, UNIT_TYPE>::storage_t storage_t; + typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> base_t; LLUnitImplicit(storage_t value = storage_t()) : base_t(value) {} - template<typename OTHER_UNIT, typename OTHER_STORAGE> - LLUnitImplicit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other) : base_t(convert(other)) {} @@ -181,53 +168,86 @@ struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE> } }; + +template<typename S1, typename T1, typename S2, typename T2> +LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...) +{ + static_assert(boost::is_same<T1, T2>::value + || !boost::is_same<T1, typename T1::base_unit_t>::value + || !boost::is_same<T2, typename T2::base_unit_t>::value, + "invalid conversion"); + + if (boost::is_same<T1, typename T1::base_unit_t>::value) + { + if (boost::is_same<T2, typename T2::base_unit_t>::value) + { + // T1 and T2 fully reduced and equal...just copy + out = (S2)in.value(); + } + else + { + // reduce T2 + LLUnit<S2, typename T2::base_unit_t> new_out; + ll_convert_units(in, new_out); + ll_convert_units(new_out, out); + } + } + else + { + // reduce T1 + LLUnit<S1, typename T1::base_unit_t> new_in; + ll_convert_units(in, new_in); + ll_convert_units(new_in, out); + } +} + // // operator + // -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result += second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result += second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result += second; return result; } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result += second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator + (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first); result += second; return result; } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result += second; return result; } @@ -235,50 +255,50 @@ LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, // // operator - // -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator - (SCALAR_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second) { - LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } @@ -286,102 +306,100 @@ LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnitImp // // operator * // -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator * (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first * second.value())); + return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first * second.value())); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() * second)); + return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() * second)); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnit<STORAGE_TYPE2, UNIT_TYPE2>) { // 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<UNIT_TYPE1, STORAGE_TYPE1>(); + return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>(); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator * (SCALAR_TYPE first, LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator * (SCALAR_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first * second.value()); + return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first * second.value()); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first.value() * second); + return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first.value() * second); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2>) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2>) { // 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<UNIT_TYPE1, STORAGE_TYPE1>(); + return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(); } // // operator / // -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { return SCALAR_TYPE(first / second.value()); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); + return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() / second)); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -STORAGE_TYPE1 operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +STORAGE_TYPE1 operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> 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<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); + return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() / second)); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -STORAGE_TYPE1 operator / (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +STORAGE_TYPE1 operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> 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<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> \ -bool operator op (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) \ +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> \ +bool operator op (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) \ { \ return first op second.value(); \ } \ \ -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> \ -bool operator op (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) \ +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> \ +bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) \ { \ return first.value() op second; \ } \ \ -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> \ -bool operator op (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) \ +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> \ +bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) \ { \ return first.value() op first.convert(second); \ } \ \ -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> \ - bool operator op (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) \ +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> \ + bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) \ { \ return first.value() op first.convert(second); \ } @@ -401,80 +419,142 @@ struct LLGetUnitLabel }; template<typename T, typename STORAGE_T> -struct LLGetUnitLabel<LLUnit<T, STORAGE_T> > +struct LLGetUnitLabel<LLUnit<STORAGE_T, T> > { static const char* getUnitLabel() { return T::getUnitLabel(); } }; -// -// Unit declarations -// -namespace LLUnits +template<typename VALUE_TYPE> +struct LLUnitLinearOps { -template<typename T> -T rawValue(T val) { return val; } + typedef LLUnitLinearOps<VALUE_TYPE> self_t; + LLUnitLinearOps(VALUE_TYPE val) : mValue (val) {} -template<typename UNIT_TYPE, typename STORAGE_TYPE> -STORAGE_TYPE rawValue(LLUnit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); } + operator VALUE_TYPE() const { return mValue; } + VALUE_TYPE mValue; -template<typename UNIT_TYPE, typename STORAGE_TYPE> -STORAGE_TYPE rawValue(LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); } + template<typename T> + self_t operator * (T other) + { + return mValue * other; + } + + template<typename T> + self_t operator / (T other) + { + return mValue / other; + } + + template<typename T> + self_t operator + (T other) + { + return mValue + other; + } + + template<typename T> + self_t operator - (T other) + { + return mValue - other; + } +}; -#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name, unit_label) \ +template<typename VALUE_TYPE> +struct LLUnitInverseLinearOps +{ + typedef LLUnitInverseLinearOps<VALUE_TYPE> self_t; + + LLUnitInverseLinearOps(VALUE_TYPE val) : mValue (val) {} + operator VALUE_TYPE() const { return mValue; } + VALUE_TYPE mValue; + + template<typename T> + self_t operator * (T other) + { + return mValue / other; + } + + template<typename T> + self_t operator / (T other) + { + return mValue * other; + } + + template<typename T> + self_t operator + (T other) + { + return mValue - other; + } + + template<typename T> + self_t operator - (T other) + { + return mValue + other; + } +}; + +#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<typename STORAGE_TYPE> \ -struct ConversionFactor<unit_name, base_unit_name, STORAGE_TYPE> \ -{ \ - static F64 get() \ - { \ - return (F64)conversion_factor; \ - } \ -}; \ \ -template<typename STORAGE_TYPE> \ -struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE> \ +template<typename S1, typename S2> \ +void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \ { \ - static F64 get() \ - { \ - return (F64)(1.0 / (conversion_factor)); \ - } \ -} + out = (S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation).mValue; \ +} \ + \ +template<typename S1, typename S2> \ +void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \ +{ \ + out = (S2)(LLUnitInverseLinearOps<S1>(in.value()) 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; }} +// +// Unit declarations +// +namespace LLUnits +{ 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", Kilobytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Kibibytes, "KiB", Bytes, * 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", 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(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", Milliseconds, / 1000); +LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, / 1000); 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", Kilohertz, * 1000); +LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, * 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..a5df51f6de 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", Latinum, / 16); } namespace tut @@ -53,105 +53,110 @@ namespace tut template<> template<> void units_object_t::test<1>() { - LLUnit<Quatloos, F32> float_quatloos; - ensure(float_quatloos.value() == 0.f); + LLUnit<F32, Quatloos> float_quatloos; + ensure(float_quatloos == 0.f); - LLUnit<Quatloos, S32> int_quatloos; - ensure(int_quatloos.value() == 0); + LLUnit<F32, Quatloos> float_initialize_quatloos(1); + ensure(float_initialize_quatloos == 1.f); + + LLUnit<S32, Quatloos> 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<Quatloos, U32> unsigned_int_quatloos(float_quatloos); - ensure(unsigned_int_quatloos.value() == 42); + ensure(int_quatloos == 42); + LLUnit<U32, Quatloos> 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, F32> quatloos(1.f); - ensure(quatloos.value() == 1.f); - LLUnit<Latinum, F32> latinum_bars(quatloos); - ensure(latinum_bars.value() == 1.f / 4.f); + LLUnit<F32, Quatloos> quatloos(1.f); + ensure(quatloos == 1.f); + LLUnit<F32, Latinum> 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, F32> solari(quatloos); - ensure(solari.value() == 4096); + LLUnit<F32, Solari> solari(quatloos); + ensure(solari == 4096); } // conversions across non-base units template<> template<> void units_object_t::test<3>() { - LLUnit<Solari, F32> solari = 4.f; - LLUnit<Latinum, F32> latinum_bars = solari; - ensure(latinum_bars.value() == 0.25f); + LLUnit<F32, Solari> solari = 4.f; + LLUnit<F32, Latinum> latinum_bars = solari; + ensure(latinum_bars == 0.25f); } // math operations template<> template<> void units_object_t::test<4>() { - LLUnit<Quatloos, F32> quatloos = 1.f; + LLUnit<F32, Quatloos> 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<Quatloos, F32>(4.f); + F32 ratio = quatloos / LLUnit<F32, Quatloos>(4.f); + ensure(ratio == 1); + ratio = quatloos / LLUnit<F32, Solari>(16.f); ensure(ratio == 1); - quatloos += LLUnit<Solari, F32>(4.f); - ensure(quatloos.value() == 5); - quatloos -= LLUnit<Latinum, F32>(1.f); - ensure(quatloos.value() == 1); + quatloos += LLUnit<F32, Solari>(4.f); + ensure(quatloos == 5); + quatloos -= LLUnit<F32, Latinum>(1.f); + ensure(quatloos == 1); } // implicit units @@ -159,16 +164,16 @@ namespace tut void units_object_t::test<5>() { // 0-initialized - LLUnit<Quatloos, F32> quatloos(0); + LLUnit<F32, Quatloos> quatloos(0); // initialize implicit unit from explicit - LLUnitImplicit<Quatloos, F32> quatloos_implicit = quatloos + 1; - ensure(quatloos_implicit.value() == 1); + LLUnitImplicit<F32, Quatloos> 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; @@ -204,5 +209,11 @@ namespace tut S32 int_val = quatloos_implicit; ensure(int_val == 16); + + // conversion of implicits + LLUnitImplicit<F32, Latinum> latinum_implicit(2); + ensure(latinum_implicit == 2); + + ensure(latinum_implicit * 2 == quatloos_implicit); } } 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<LLUnits::Bytes, S32> LLImageGL::sGlobalTextureMemory = 0; -LLUnit<LLUnits::Bytes, S32> LLImageGL::sBoundTextureMemory = 0; -LLUnit<LLUnits::Bytes, S32> LLImageGL::sCurBoundTextureMemory = 0; +LLUnit<S32, LLUnits::Bytes> LLImageGL::sGlobalTextureMemory = 0; +LLUnit<S32, LLUnits::Bytes> LLImageGL::sBoundTextureMemory = 0; +LLUnit<S32, LLUnits::Bytes> 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<LLUnits::Bytes, S32> sGlobalTextureMemory; // Tracks main memory texmem - static LLUnit<LLUnits::Bytes, S32> sBoundTextureMemory; // Tracks bound texmem for last completed frame - static LLUnit<LLUnits::Bytes, S32> sCurBoundTextureMemory; // Tracks bound texmem for current frame + static LLUnit<S32, LLUnits::Bytes> sGlobalTextureMemory; // Tracks main memory texmem + static LLUnit<S32, LLUnits::Bytes> sBoundTextureMemory; // Tracks bound texmem for last completed frame + static LLUnit<S32, LLUnits::Bytes> 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..8c51bd4198 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<LLUnits::Seconds, F32> gFrameIntervalSeconds = 0.f; +LLUnit<F32, LLUnits::Seconds> 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 @@ -1248,7 +1248,7 @@ static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback"); static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot"); static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update"); -LLFastTimer::DeclareTimer FTM_FRAME("Frame", true); +LLFastTimer::DeclareTimer FTM_FRAME("Frame"); bool LLAppViewer::mainLoop() { 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<LLUnits::Seconds, F32> gFrameIntervalSeconds; // Elapsed time between current and previous gFrameTimeSeconds +extern LLUnit<F32, LLUnits::Seconds> 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/lldrawable.cpp b/indra/newview/lldrawable.cpp index 30d1b7fdba..8587c7852b 100755 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -300,7 +300,7 @@ S32 LLDrawable::findReferences(LLDrawable *drawablep) return count; } -static LLFastTimer::DeclareTimer FTM_ALLOCATE_FACE("Allocate Face", true); +static LLFastTimer::DeclareTimer FTM_ALLOCATE_FACE("Allocate Face"); LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerTexture *texturep) { diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 40526d3357..ec307b841e 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" @@ -56,9 +58,11 @@ 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; +static const S32 RUNNING_AVERAGE_WIDTH = 100; +static const S32 NUM_FRAMES_HISTORY = 256; std::vector<TimeBlock*> ft_display_idx; // line of table entry for display purposes (for collapse) @@ -95,27 +99,19 @@ 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), - mPrintStats(-1), - mRecording(&get_frame_recording()), - mPauseHistory(false) + mStatsIndex(-1), + mPauseHistory(false), + mRecording(NUM_FRAMES_HISTORY) { - mTimerBars = new std::vector<TimerBar>[MAX_VISIBLE_HISTORY + 1]; + mTimerBarRows.resize(NUM_FRAMES_HISTORY); } LLFastTimerView::~LLFastTimerView() { - if (mRecording != &get_frame_recording()) - { - delete mRecording; - } - mRecording = NULL; - delete [] mTimerBars; } void LLFastTimerView::onPause() @@ -130,16 +126,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<LLButton>("pause_btn")->setLabel(getString("pause")); } else { - mRecording = new PeriodicRecording(get_frame_recording()); mScrollIndex = 0; getChild<LLButton>("pause_btn")->setLabel(getString("run")); @@ -161,13 +152,13 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) if (mHoverTimer ) { // right click collapses timers - if (!mHoverTimer->getCollapsed()) + if (!mHoverTimer->getTreeNode().mCollapsed) { - mHoverTimer->setCollapsed(true); + mHoverTimer->getTreeNode().mCollapsed = true; } else if (mHoverTimer->getParent()) { - mHoverTimer->getParent()->setCollapsed(true); + mHoverTimer->getParent()->getTreeNode().mCollapsed = true; } return TRUE; } @@ -175,7 +166,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); @@ -183,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()) { @@ -199,7 +190,7 @@ BOOL LLFastTimerView::handleDoubleClick(S32 x, S32 y, MASK mask) it != end_timer_tree(); ++it) { - (*it)->setCollapsed(false); + (*it)->getTreeNode().mCollapsed = false; } return TRUE; } @@ -211,33 +202,13 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) TimeBlock* idp = getLegendID(y); if (idp) { - idp->setCollapsed(!idp->getCollapsed()); + idp->getTreeNode().mCollapsed = !idp->getTreeNode().mCollapsed; } } else if (mHoverTimer) { //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); + mHoverTimer->getTreeNode().mCollapsed = false; } else if (mGraphRect.pointInRect(x, y)) { @@ -262,8 +233,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; @@ -271,8 +242,11 @@ 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, + //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) { @@ -283,30 +257,44 @@ 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[mScrollIndex + mHoverBarIndex - 1]; + + TimerBar* hover_bar = NULL; + LLUnit<F32, LLUnits::Seconds> mouse_time_offset = ((F32)(x - mBarRect.mLeft) / (F32)mBarRect.getWidth()) * mTotalTimeDisplay; + for (int bar_index = 0, end_index = LLInstanceTracker<LLTrace::TimeBlock>::instanceCount(); + bar_index < end_index; + ++bar_index) { - // is mouse over bar for this timer? - if (mTimerBars[mHoverBarIndex][i].mVisibleRect.pointInRect(x, y)) + TimerBar& bar = row.mBars[bar_index]; + if (bar.mSelfStart > mouse_time_offset) + { + break; + } + if (bar.mSelfEnd > mouse_time_offset) { - mHoverID = (*it); - if (mHoverTimer != *it) + hover_bar = &bar; + if (bar.mTimeBlock->getTreeNode().mCollapsed) { - // 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); + // stop on first collapsed timeblock, since we can't select any children + break; } - - mToolTipRect = mTimerBars[mHoverBarIndex][i].mVisibleRect; } + } - if ((*it)->getCollapsed()) + if (hover_bar) + { + mHoverID = hover_bar->mTimeBlock; + 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->mSelfEnd / mTotalTimeDisplay) * mBarRect.getWidth(), + row.mBottom); } } } @@ -329,11 +317,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<LLUnits::Milliseconds, F64>(frame_recording.getPeriodMean(timer)).value(), (S32)frame_recording.getPeriodMean(timer.callCount())); + tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit<F64, LLUnits::Milliseconds>(frame_recording.getPeriodMean (timer, RUNNING_AVERAGE_WIDTH)).value(), (S32)frame_recording.getPeriodMean(timer.callCount(), RUNNING_AVERAGE_WIDTH)); } else { - tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit<LLUnits::Milliseconds, F64>(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<F64, LLUnits::Milliseconds>(frame_recording.getPrevRecording(history_index).getSum(timer)).value(), (S32)frame_recording.getPrevRecording(history_index).getSum(timer.callCount())); } return tooltip; } @@ -348,7 +336,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 +354,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,47 +369,81 @@ 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; } -static TimeBlock FTM_RENDER_TIMER("Timers", true); +static TimeBlock FTM_RENDER_TIMER("Timers"); static const S32 MARGIN = 10; static const S32 LEGEND_WIDTH = 220; -static std::map<TimeBlock*, LLColor4> sTimerColors; +static std::vector<LLColor4> 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()); + } + + mDisplayMode = llclamp(getChild<LLComboBox>("time_scale_combo")->getCurrentIndex(), 0, 3); + mDisplayType = (EDisplayType)llclamp(getChild<LLComboBox>("metric_combo")->getCurrentIndex(), 0, 2); + generateUniqueColors(); + LLView::drawChildren(); + //getChild<LLLayoutStack>("timer_bars_stack")->updateLayout(); + //getChild<LLLayoutStack>("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)); + drawHelp(getRect().getHeight() - MARGIN); + drawLegend(); - // update rectangle that includes timer bars - const S32 LEGEND_WIDTH = 220; - - 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(); 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) +{ + setPauseState(false); + mRecording.reset(); + mRecording.appendPeriodicRecording(LLTrace::get_frame_recording()); + for(std::deque<TimerBarRow>::iterator it = mTimerBarRows.begin(), end_it = mTimerBarRows.end(); + it != end_it; + ++it) + { + delete []it->mBars; + it->mBars = NULL; + } +} + + void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch) { //read result back into raw image @@ -828,7 +850,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 +958,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; @@ -953,7 +975,7 @@ void LLFastTimerView::printLineStats() first = false; legend_stat += idp->getName(); - if (idp->getCollapsed()) + if (idp->getTreeNode().mCollapsed) { it.skipDescendants(); } @@ -974,26 +996,26 @@ void LLFastTimerView::printLineStats() } first = false; - LLUnit<LLUnits::Seconds, F32> ticks; - if (mPrintStats > 0) + LLUnit<F32, LLUnits::Seconds> ticks; + if (mStatsIndex == 0) { - ticks = mRecording->getPrevRecording(mPrintStats).getSum(*idp); + ticks = mRecording.getPeriodMean(*idp, RUNNING_AVERAGE_WIDTH); } else { - ticks = mRecording->getPeriodMean(*idp); + ticks = mRecording.getPrevRecording(mStatsIndex).getSum(*idp); } - LLUnit<LLUnits::Milliseconds, F32> ms = ticks; + LLUnit<F32, LLUnits::Milliseconds> ms = ticks; timer_stat += llformat("%.1f",ms.value()); - if (idp->getCollapsed()) + if (idp->getTreeNode().mCollapsed) { it.skipDescendants(); } } llinfos << timer_stat << llendl; - mPrintStats = -1; + mStatsIndex = -1; } } @@ -1003,37 +1025,20 @@ 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); //normalize based on last frame's maximum - static LLUnit<LLUnits::Seconds, F32> max_time = 0.000001; + static LLUnit<F32, LLUnits::Seconds> max_time = 0.000001; 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<LLUnits::Milliseconds, F32>(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->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; @@ -1043,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); @@ -1055,7 +1060,7 @@ void LLFastTimerView::drawLineGraph() } } - LLUnit<LLUnits::Seconds, F32> cur_max = 0; + LLUnit<F32, LLUnits::Seconds> cur_max = 0; U32 cur_max_calls = 0; for(timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); it != end_timer_tree(); @@ -1070,9 +1075,11 @@ void LLFastTimerView::drawLineGraph() glLineWidth(3); } - const F32 * col = sTimerColors[idp].mV;// ft_display_table[idx].color->mV; + llassert(idp->getIndex() < sTimerColors.size()); + 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) @@ -1080,28 +1087,43 @@ 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); - for (U32 j = mRecording->getNumPeriods(); + 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--) { - LLUnit<LLUnits::Seconds, F32> time = llmax(mRecording->getPrevRecording(j).getSum(*idp), LLUnit<LLUnits::Seconds, F64>(0.000001)); - U32 calls = mRecording->getPrevRecording(j).getSum(idp->callCount()); + LLTrace::Recording& recording = mRecording.getPrevRecording(j); + LLUnit<F32, LLUnits::Seconds> time = llmax(recording.getSum(*idp), LLUnit<F64, LLUnits::Seconds>(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->getNumPeriods()-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 x = mGraphRect.mRight - j * (F32)(mGraphRect.getWidth())/(mRecording.getNumRecordedPeriods()-1); + 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); } @@ -1113,7 +1135,7 @@ void LLFastTimerView::drawLineGraph() glLineWidth(1); } - if (idp->getCollapsed()) + if (idp->getTreeNode().mCollapsed) { //skip hidden timers it.skipDescendants(); @@ -1122,9 +1144,9 @@ 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<LLUnits::Microseconds, F32>(1), LLUnit<LLUnits::Microseconds, F32>(cur_max)); + max_time = llmax(LLUnit<F32, LLUnits::Microseconds>(1), LLUnit<F32, LLUnits::Microseconds>(cur_max)); } max_calls = llround(lerp((F32)max_calls, (F32) cur_max_calls, LLSmoothInterpolation::getInterpolant(0.1f))); @@ -1141,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(), @@ -1150,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<F32, LLUnits::Milliseconds>(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<TimeBlock*, S32> display_line; @@ -1183,30 +1227,35 @@ 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]); + llassert(idp->getIndex() < sTimerColors.size()); + gl_rect_2d(bar_rect, sTimerColors[idp->getIndex()]); - LLUnit<LLUnits::Milliseconds, F32> ms = 0; + LLUnit<F32, LLUnits::Milliseconds> 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<LLUnits::Seconds, F64>(mRecording->getPeriodMean(*idp)); - calls = (S32)mRecording->getPeriodMean(idp->callCount()); + ms = LLUnit<F64, LLUnits::Seconds>(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; @@ -1218,7 +1267,7 @@ void LLFastTimerView::drawLegend( S32 y ) gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color); S32 line_x = x + (TEXT_HEIGHT + 4) + ((get_depth(idp) - 1) * 8); gl_line_2d(line_x, line_start_y, line_x, line_end_y, color); - if (idp->getCollapsed() && !idp->getChildren().empty()) + if (idp->getTreeNode().mCollapsed && !idp->getChildren().empty()) { gl_line_2d(line_x+4, line_start_y-3, line_x+4, line_start_y+4, color); } @@ -1242,7 +1291,7 @@ void LLFastTimerView::drawLegend( S32 y ) y -= (TEXT_HEIGHT + 2); - if (idp->getCollapsed()) + if (idp->getTreeNode().mCollapsed) { it.skipDescendants(); } @@ -1254,7 +1303,8 @@ void LLFastTimerView::generateUniqueColors() { // generate unique colors { - sTimerColors[&FTM_FRAME] = LLColor4::grey; + sTimerColors.resize(LLTrace::TimeBlock::getNumIndices()); + sTimerColors[FTM_FRAME.getIndex()] = LLColor4::grey; F32 hue = 0.f; @@ -1274,48 +1324,29 @@ void LLFastTimerView::generateUniqueColors() LLColor4 child_color; child_color.setHSL(hue, saturation, lightness); - sTimerColors[idp] = child_color; + llassert(idp->getIndex() < sTimerColors.size()); + sTimerColors[idp->getIndex()] = child_color; } } } -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() { // Draw MS ticks { - LLUnit<LLUnits::Milliseconds, U32> ms = mTotalTimeDisplay; + LLUnit<U32, LLUnits::Milliseconds> ms = mTotalTimeDisplay; std::string tick_label; S32 x; S32 barw = mBarRect.getWidth(); @@ -1368,10 +1399,10 @@ 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); + //mGraphRect = LLRect(x_start-5, by, getRect().getWidth()-5, 5); gl_rect_2d(mGraphRect, FALSE); } @@ -1382,210 +1413,251 @@ void LLFastTimerView::updateTotalTime() switch(mDisplayMode) { case 0: - mTotalTimeDisplay = mRecording->getPeriodMean(FTM_FRAME)*2; + mTotalTimeDisplay = mRecording.getPeriodMean(FTM_FRAME, RUNNING_AVERAGE_WIDTH)*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<LLUnits::Milliseconds, F32>(100); + mTotalTimeDisplay = LLUnit<F32, LLUnits::Milliseconds>(100); break; } - mTotalTimeDisplay = LLUnit<LLUnits::Milliseconds, F32>(llceil(mTotalTimeDisplay.as<LLUnits::Milliseconds>().value() / 20.f) * 20.f); + mTotalTimeDisplay = LLUnit<F32, LLUnits::Milliseconds>(llceil(mTotalTimeDisplay.getAs<LLUnits::Milliseconds>() / 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<LLUIImage> 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 = (S32)mRecording.getNumRecordedPeriods(); - 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<LLTrace::TimeBlock>::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; - } + // update widths + if (!mPauseHistory) + { + U32 bar_index = 0; + if (!mAverageTimerRow.mBars) + { + mAverageTimerRow.mBars = new TimerBar[LLInstanceTracker<LLTrace::TimeBlock>::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<LLTrace::TimeBlock>::instanceCount()]; + updateTimerBarWidths(&FTM_FRAME, row, history_index, bar_index); + updateTimerBarOffsets(&FTM_FRAME, row); + } + } + } + + // draw bars + 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(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; + 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)); + } + + } 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<TimerBar>& bars, S32 history_index, bool visible) +LLUnit<F32, LLUnits::Seconds> LLFastTimerView::updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, U32& bar_index) { 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); - - S32 self_time_width = llround(self_time_frame_fraction * (F32)mBarRect.getWidth()); - S32 full_width = self_time_width; + const LLUnit<F32, LLUnits::Seconds> self_time = history_index == -1 + ? mRecording.getPeriodMean(time_block->selfTime(), RUNNING_AVERAGE_WIDTH) + : mRecording.getPrevRecording(history_index).getSum(time_block->selfTime()); - bool children_visible = visible; + LLUnit<F32, LLUnits::Seconds> 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 - S32 bar_rect_index = bars.size(); - if (visible) - { - bars.push_back(TimerBar()); - } + TimerBar& timer_bar = row.mBars[bar_index]; + bar_index++; - if (time_block->getCollapsed()) - { - children_visible = false; - } 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_time += updateTimerBarWidths(*it, row, history_index, bar_index); } - 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); - } - } - return full_width; + timer_bar.mTotalTime = full_time; + timer_bar.mSelfTime = self_time; + timer_bar.mTimeBlock = time_block; + + return full_time; } 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<TimerBar>& bars) +S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 timer_bar_index) { LLFastTimer _(FTM_UPDATE_TIMER_BAR_FRACTIONS); - TimerBar& timer_bar = bars[timer_bar_index]; - S32 child_time_width = timer_bar.mWidth - timer_bar.mSelfWidth; - LLRect children_rect = timer_bar.mVisibleRect; - if (mDisplayCenter == ALIGN_CENTER) - { - children_rect.mLeft += timer_bar.mSelfWidth / 2; - } - else if (mDisplayCenter == ALIGN_RIGHT) - { - children_rect.mLeft += timer_bar.mSelfWidth; - } - children_rect.mRight = children_rect.mLeft + timer_bar.mWidth - timer_bar.mSelfWidth; + TimerBar& timer_bar = row.mBars[timer_bar_index]; + const LLUnit<F32, LLUnits::Seconds> 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 (children_rect.getHeight() > MIN_BAR_HEIGHT) + if (timer_bar_index == 0) { - children_rect.mTop -= 1; - children_rect.mBottom += 1; + timer_bar.mSelfStart = 0.f; + timer_bar.mSelfEnd = bar_time; } - 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 //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++; + + TimerBar& child_timer_bar = row.mBars[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 = 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); - timer_bar_index = updateTimerBarFractions(child_time_block, timer_bar_index, bars); + 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, std::vector<TimerBar>& bars, S32 bar_index, LLPointer<LLUIImage>& bar_image) +S32 LLFastTimerView::drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, bool visible, S32 bar_index) { - TimerBar& timer_bar = bars[bar_index]; + 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 (visible && (F32)bar_rect.getWidth() * (timer_bar.mEndFraction - timer_bar.mStartFraction) > 2.f) { 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); + llassert(time_block->getIndex() < sTimerColors.size()); + LLColor4 color = sTimerColors[time_block->getIndex()]; + if (!hovered) color = lerp(color, LLColor4::grey, 0.2f); + 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); } - 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) + { + // 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; + } + + bool children_visible = visible && !time_block->getTreeNode().mCollapsed; + + bar_index++; + const U32 num_bars = LLInstanceTracker<LLTrace::TimeBlock>::instanceCount(); + if (bar_index < num_bars && row.mBars[bar_index].mFirstChild) { - for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); it != end_it; ++it) + bool is_last = false; + do { - ++bar_index; - bar_index = drawBar(*it, timer_bar.mChildrenRect, bars, bar_index, bar_image); + is_last = row.mBars[bar_index].mLastChild; + bar_index = drawBar(children_rect, row, image_width, image_height, hovered, children_visible, 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 341adacd65..d931f25a7e 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 <deque> class LLFastTimerView : public LLFloater { @@ -60,17 +61,15 @@ 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); - S32 drawHelp(S32 y); + void drawLegend(); + void drawHelp(S32 y); void drawBorders( S32 y, const S32 x_start, S32 barh, S32 dy); void drawBars(); @@ -81,53 +80,63 @@ private: struct TimerBar { TimerBar() - : mWidth(0), - mSelfWidth(0), - mVisible(true), + : mTotalTime(0), + mSelfTime(0), mStartFraction(0.f), - mEndFraction(1.f) + mEndFraction(1.f), + mFirstChild(false), + mLastChild(false) {} - S32 mWidth; - S32 mSelfWidth; - LLRect mVisibleRect, - mChildrenRect; - LLColor4 mColor; - bool mVisible; - F32 mStartFraction, - mEndFraction; + LLUnit<F32, LLUnits::Seconds> mTotalTime, + mSelfTime, + mChildrenStart, + mChildrenEnd, + mSelfStart, + mSelfEnd; + LLTrace::TimeBlock* mTimeBlock; + bool mVisible, + mFirstChild, + mLastChild; + F32 mStartFraction, + mEndFraction; }; - S32 updateTimerBarWidths(LLTrace::TimeBlock* time_block, std::vector<TimerBar>& bars, S32 history_index, bool visible); - S32 updateTimerBarFractions(LLTrace::TimeBlock* time_block, S32 timer_bar_index, std::vector<TimerBar>& bars); - S32 drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, std::vector<TimerBar>& bars, S32 bar_index, LLPointer<LLUIImage>& bar_image); + + struct TimerBarRow + { + S32 mBottom, + mTop; + TimerBar* mBars; + }; + + LLUnit<F32, LLUnits::Seconds> 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, bool visible = true, S32 bar_index = 0); void setPauseState(bool pause_state); - std::vector<TimerBar>* mTimerBars; - S32 mDisplayMode; + std::deque<TimerBarRow> mTimerBarRows; + TimerBarRow mAverageTimerRow; - typedef enum child_alignment + enum EDisplayType { - ALIGN_LEFT, - ALIGN_CENTER, - ALIGN_RIGHT, - ALIGN_COUNT - } ChildAlignment; - - ChildAlignment mDisplayCenter; - bool mDisplayCalls, - mDisplayHz; - LLUnit<LLUnits::Seconds, F64> 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; + TIME, + CALLS, + HZ + } mDisplayType; + bool mPauseHistory; + LLUnit<F64, LLUnits::Seconds> mAllTimeMax, + mTotalTimeDisplay; + S32 mScrollIndex, + mHoverBarIndex, + mStatsIndex; + S32 mDisplayMode; + LLTrace::TimeBlock* mHoverID; + LLTrace::TimeBlock* mHoverTimer; + LLRect mToolTipRect, + mGraphRect, + mBarRect, + mLegendRect; + LLFrameTimer mHighlightTimer; + LLTrace::PeriodicRecording mRecording; }; #endif diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index dccf8a2a17..8086745471 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<LLUnits::Seconds, F64> frame_time; + LLUnit<F64, LLUnits::Seconds> frame_time; os << "Stat"; for (S32 frame = 0; frame < frame_count; frame++) @@ -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<LLUnits::Kibibytes>().value(); + os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(*it).getAs<LLUnits::Kibibytes>(); } os << std::endl; 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<LLUnits::Bits, U32> mHTTPTextureBits; // Mfnq + LLUnit<U32, LLUnits::Bits> 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<LLUnits::Mibibytes, S32> bound_mem = LLViewerTexture::sBoundTextureMemory; - LLUnit<LLUnits::Mibibytes, S32> max_bound_mem = LLViewerTexture::sMaxBoundTextureMem; - LLUnit<LLUnits::Mibibytes, S32> total_mem = LLViewerTexture::sTotalTextureMemory; - LLUnit<LLUnits::Mibibytes, S32> max_total_mem = LLViewerTexture::sMaxTotalTextureMem; + LLUnit<S32, LLUnits::Mibibytes> bound_mem = LLViewerTexture::sBoundTextureMemory; + LLUnit<S32, LLUnits::Mibibytes> max_bound_mem = LLViewerTexture::sMaxBoundTextureMem; + LLUnit<S32, LLUnits::Mibibytes> total_mem = LLViewerTexture::sTotalTextureMemory; + LLUnit<S32, LLUnits::Mibibytes> 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<LLUnits::Bytes, F32> total_texture_downloaded = gTotalTextureData; - LLUnit<LLUnits::Bytes, F32> total_object_downloaded = gTotalObjectData; + LLUnit<F32, LLUnits::Bytes> total_texture_downloaded = gTotalTextureData; + LLUnit<F32, LLUnits::Bytes> 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<LLUnits::Microseconds, F64>(rec.getDuration()).value()); + r.duration(LLUnit<F64, LLUnits::Microseconds>(rec.getDuration()).value()); } - stats.duration(mCurRecording ? LLUnit<LLUnits::Microseconds, F64>(mCurRecording->getDuration()).value() : 0.0); + stats.duration(mCurRecording ? LLUnit<F64, LLUnits::Microseconds>(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<LLUnits::Microseconds, U64> duration_t; + typedef LLUnit<U64, LLUnits::Microseconds> duration_t; /** * Type for the region identifier used in stats. Currently uses diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 7ad4743d82..bd85056d70 100755 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -210,7 +210,7 @@ void display_stats() } static LLFastTimer::DeclareTimer FTM_PICK("Picking"); -static LLFastTimer::DeclareTimer FTM_RENDER("Render", true); +static LLFastTimer::DeclareTimer FTM_RENDER("Render"); static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky"); static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images"); 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<LLUnits::Bits, U32> gObjectData; +extern LLUnit<U32, LLUnits::Bits> gObjectData; void process_object_update(LLMessageSystem *mesgsys, void **user_data) { // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveCompressedSize(); + gObjectData += (LLUnit<U32, LLUnits::Bytes>)mesgsys->getReceiveCompressedSize(); } else { - gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveSize(); + gObjectData += (LLUnit<U32, LLUnits::Bytes>)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<LLUnits::Bytes, U32>)mesgsys->getReceiveCompressedSize(); + gObjectData += (LLUnit<U32, LLUnits::Bytes>)mesgsys->getReceiveCompressedSize(); } else { - gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveSize(); + gObjectData += (LLUnit<U32, LLUnits::Bytes>)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<LLUnits::Bytes, U32>)mesgsys->getReceiveCompressedSize(); + gObjectData += (LLUnit<U32, LLUnits::Bytes>)mesgsys->getReceiveCompressedSize(); } else { - gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveSize(); + gObjectData += (LLUnit<U32, LLUnits::Bytes>)mesgsys->getReceiveSize(); } // Update the object... @@ -4535,11 +4535,11 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_ { if (mesgsys->getReceiveCompressedSize()) { - gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveCompressedSize(); + gObjectData += (LLUnit<U32, LLUnits::Bytes>)mesgsys->getReceiveCompressedSize(); } else { - gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveSize(); + gObjectData += (LLUnit<U32, LLUnits::Bytes>)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<LLUnits::Bytes, U32> gTotalWorldData = 0, +LLUnit<U32, LLUnits::Bytes> gTotalWorldData = 0, gTotalObjectData = 0, gTotalTextureData = 0; U32 gSimPingCount = 0; -LLUnit<LLUnits::Bits, U32> gObjectData = 0; +LLUnit<U32, LLUnits::Bits> gObjectData = 0; F32 gAvgSimPing = 0.f; -LLUnit<LLUnits::Bytes, U32> gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0}; +LLUnit<U32, LLUnits::Bytes> gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0}; extern U32 gVisCompared; extern U32 gVisTested; @@ -334,8 +334,8 @@ void update_statistics() typedef LLInstanceTracker<LLTrace::TraceType<LLTrace::TimeBlockAccumulator>, std::string> trace_type_t; - LLUnit<LLUnits::Seconds, F64> idle_secs = last_frame_recording.getSum(*trace_type_t::getInstance("Idle")); - LLUnit<LLUnits::Seconds, F64> network_secs = last_frame_recording.getSum(*trace_type_t::getInstance("Network")); + LLUnit<F64, LLUnits::Seconds> idle_secs = last_frame_recording.getSum(*trace_type_t::getInstance("Idle")); + LLUnit<F64, LLUnits::Seconds> 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<LLUnits::Bytes, U32> gTotalTextureData; -extern LLUnit<LLUnits::Bytes, U32> gTotalObjectData; -extern LLUnit<LLUnits::Bytes, U32> gTotalTextureBytesPerBoostLevel[] ; +extern LLUnit<U32, LLUnits::Bytes> gTotalTextureData; +extern LLUnit<U32, LLUnits::Bytes> gTotalObjectData; +extern LLUnit<U32, LLUnits::Bytes> 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<LLUnits::Mibibytes, S32> gMinVideoRam = 32; -const LLUnit<LLUnits::Mibibytes, S32> gMaxVideoRam = 512; +const LLUnit<S32, LLUnits::Mibibytes> gMinVideoRam = 32; +const LLUnit<S32, LLUnits::Mibibytes> 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<LLUnits::Bytes, S32> LLViewerTexture::sBoundTextureMemory = 0; -LLUnit<LLUnits::Bytes, S32> LLViewerTexture::sTotalTextureMemory = 0; -LLUnit<LLUnits::Mibibytes, S32> LLViewerTexture::sMaxBoundTextureMem = 0; -LLUnit<LLUnits::Mibibytes, S32> LLViewerTexture::sMaxTotalTextureMem = 0; -LLUnit<LLUnits::Bytes, S32> LLViewerTexture::sMaxDesiredTextureMem = 0 ; +LLUnit<S32, LLUnits::Bytes> LLViewerTexture::sBoundTextureMemory = 0; +LLUnit<S32, LLUnits::Bytes> LLViewerTexture::sTotalTextureMemory = 0; +LLUnit<S32, LLUnits::Mibibytes> LLViewerTexture::sMaxBoundTextureMem = 0; +LLUnit<S32, LLUnits::Mibibytes> LLViewerTexture::sMaxTotalTextureMem = 0; +LLUnit<S32, LLUnits::Bytes> 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<LLUnits::Bytes, S32>(gMaxVideoRam)); + sMaxDesiredTextureMem = llmin(sMaxDesiredTextureMem * 0.75f, LLUnit<S32, LLUnits::Bytes>(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 <map> #include <list> -extern const LLUnit<LLUnits::Mibibytes, S32> gMinVideoRam; -extern const LLUnit<LLUnits::Mibibytes, S32> gMaxVideoRam; +extern const LLUnit<S32, LLUnits::Mibibytes> gMinVideoRam; +extern const LLUnit<S32, LLUnits::Mibibytes> gMaxVideoRam; class LLFace; class LLImageGL ; @@ -205,11 +205,11 @@ public: static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; static F32 sDesiredDiscardScale; - static LLUnit<LLUnits::Bytes, S32> sBoundTextureMemory; - static LLUnit<LLUnits::Bytes, S32> sTotalTextureMemory; - static LLUnit<LLUnits::Mibibytes, S32> sMaxBoundTextureMem; - static LLUnit<LLUnits::Mibibytes, S32> sMaxTotalTextureMem; - static LLUnit<LLUnits::Bytes, S32> sMaxDesiredTextureMem ; + static LLUnit<S32, LLUnits::Bytes> sBoundTextureMemory; + static LLUnit<S32, LLUnits::Bytes> sTotalTextureMemory; + static LLUnit<S32, LLUnits::Mibibytes> sMaxBoundTextureMem; + static LLUnit<S32, LLUnits::Mibibytes> sMaxTotalTextureMem; + static LLUnit<S32, LLUnits::Bytes> 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<LLUnits::Mibibytes, F32>(gTotalTextureBytesPerBoostLevel[i]).value())); + addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, LLUnit<F32, LLUnits::Mibibytes>(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<LLUnits::Seconds, F32>(max_dtime)); + max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, LLUnitImplicit<F32, LLUnits::Seconds>(max_dtime)); LLSpatialGroup* last_group = NULL; LLSpatialBridge* last_bridge = NULL; 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"> <string name="pause" >Pause</string> <string name="run">Run</string> + <combo_box name="time_scale_combo" + follows="left|top" + left="10" + top="5" + width="150" + height="20"> + <item label="2x Average"/> + <item label="Max"/> + <item label="Recent Max"/> + <item label="100ms"/> + </combo_box> + <combo_box name="metric_combo" + follows="left|top" + left_pad="10" + top="5" + width="150" + height="20"> + <item label="Time"/> + <item label="Number of Calls"/> + <item label="Hz"/> + </combo_box> <button follows="top|right" name="pause_btn" left="-200" @@ -24,4 +45,52 @@ height="40" label="Pause" font="SansSerifHuge"/> + <layout_stack name="legend_stack" + orientation="horizontal" + left="0" + top="50" + right="695" + bottom="500" + follows="all"> + <layout_panel name="legend_panel" + auto_resize="false" + user_resize="true" + width="220" + height="450" + min_width="100"> + <panel top="0" + left="0" + width="220" + height="440" + name="legend" + follows="all"/> + </layout_panel> + <layout_panel name="timers_panel" + auto_resize="true" + user_resize="true" + height="450" + width="475" + min_width="100"> + <layout_stack name="timer_bars_stack" + orientation="vertical" + left="0" + top="0" + width="475" + height="445" + follows="all"> + <layout_panel name="bars_panel" + auto_resize="true" + user_resize="true" + top="0" + width="475" + height="210"/> + <layout_panel name="lines_panel" + auto_resize="false" + user_resize="true" + width="475" + min_height="50" + height="240"/> + </layout_stack> + </layout_panel> + </layout_stack> </floater> |