summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rwxr-xr-xindra/llcharacter/llkeyframewalkmotion.cpp2
-rwxr-xr-xindra/llcommon/llcriticaldamp.cpp2
-rwxr-xr-xindra/llcommon/llcriticaldamp.h4
-rwxr-xr-xindra/llcommon/lldate.cpp2
-rwxr-xr-xindra/llcommon/lldate.h2
-rwxr-xr-xindra/llcommon/llfasttimer.cpp95
-rwxr-xr-xindra/llcommon/llfasttimer.h6
-rwxr-xr-xindra/llcommon/llprocessor.cpp2
-rwxr-xr-xindra/llcommon/llprocessor.h2
-rwxr-xr-xindra/llcommon/lltimer.cpp14
-rwxr-xr-xindra/llcommon/lltimer.h16
-rw-r--r--indra/llcommon/lltrace.h103
-rw-r--r--indra/llcommon/lltracerecording.cpp238
-rw-r--r--indra/llcommon/lltracerecording.h58
-rw-r--r--indra/llcommon/lltracethreadrecorder.cpp1
-rw-r--r--indra/llcommon/llunit.h442
-rw-r--r--indra/llcommon/tests/llunits_test.cpp113
-rw-r--r--indra/llrender/llimagegl.cpp6
-rwxr-xr-xindra/llrender/llimagegl.h6
-rwxr-xr-xindra/llui/llstatbar.cpp4
-rwxr-xr-xindra/newview/llappviewer.cpp2
-rwxr-xr-xindra/newview/llappviewer.h2
-rwxr-xr-xindra/newview/llfasttimerview.cpp640
-rwxr-xr-xindra/newview/llfasttimerview.h101
-rw-r--r--indra/newview/llscenemonitor.cpp6
-rwxr-xr-xindra/newview/lltexturefetch.h2
-rwxr-xr-xindra/newview/lltextureview.cpp12
-rwxr-xr-xindra/newview/llviewerassetstats.cpp4
-rwxr-xr-xindra/newview/llviewerassetstats.h2
-rwxr-xr-xindra/newview/llviewermessage.cpp18
-rwxr-xr-xindra/newview/llviewerstats.cpp10
-rwxr-xr-xindra/newview/llviewerstats.h6
-rwxr-xr-xindra/newview/llviewertexture.cpp16
-rwxr-xr-xindra/newview/llviewertexture.h14
-rwxr-xr-xindra/newview/llviewerwindow.cpp2
-rwxr-xr-xindra/newview/pipeline.cpp2
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_fast_timers.xml69
37 files changed, 1135 insertions, 891 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..4da9c3fd6c 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -146,8 +146,8 @@ U64 TimeBlock::countsPerSecond()
{
#if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
- static LLUnit<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,8 +159,8 @@ U64 TimeBlock::countsPerSecond()
QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency);
firstcall = false;
}
-#endif
return sCPUClockFrequency.value();
+#endif
}
#endif
@@ -178,43 +178,38 @@ TimeBlockTreeNode& TimeBlock::getTreeNode() const
return *nodep;
}
-static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times");
-// not thread safe, so only call on main thread
-//static
-void TimeBlock::processTimes()
+void TimeBlock::bootstrapTimerTree()
{
- LLFastTimer _(FTM_PROCESS_TIMES);
- get_clock_count(); // good place to calculate clock frequency
- U64 cur_time = getCPUClockCount64();
-
- // set up initial tree
for (LLInstanceTracker<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 +235,35 @@ void TimeBlock::processTimes()
LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
" to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL;
timerp->setParent(timerp->getParent()->getParent());
- accumulator->mParent = timerp->getParent();
- accumulator->mMoveUpTree = false;
+ accumulator->mParent = timerp->getParent();
+ accumulator->mMoveUpTree = false;
// don't bubble up any ancestors until descendants are done bubbling up
- // as ancestors may call this timer only on certain paths, so we want to resolve
- // child-most block locations before their parents
+ // as ancestors may call this timer only on certain paths, so we want to resolve
+ // child-most block locations before their parents
it.skipAncestors();
}
}
}
+}
+
+
+void TimeBlock::updateTimes()
+{
+ U64 cur_time = getCPUClockCount64();
// walk up stack of active timers and accumulate current time while leaving timing structures active
- BlockTimerStackRecord* stack_record = ThreadTimerStack::getInstance();
- BlockTimer* cur_timer = stack_record->mActiveTimer;
- TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
+ BlockTimerStackRecord* stack_record = ThreadTimerStack::getInstance();
+ BlockTimer* cur_timer = stack_record->mActiveTimer;
+ TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
while(cur_timer
&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
{
U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
- accumulator->mTotalTimeCounter += cumulative_time_delta - (accumulator->mTotalTimeCounter - cur_timer->mBlockStartTotalTimeCounter);
+ accumulator->mTotalTimeCounter += cumulative_time_delta
+ - (accumulator->mTotalTimeCounter
+ - cur_timer->mBlockStartTotalTimeCounter);
accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
stack_record->mChildTime = 0;
@@ -268,11 +271,28 @@ void TimeBlock::processTimes()
cur_timer->mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
stack_record = &cur_timer->mParentTimerData;
- accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
- cur_timer = stack_record->mActiveTimer;
+ accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
+ cur_timer = stack_record->mActiveTimer;
stack_record->mChildTime += cumulative_time_delta;
}
+}
+
+static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times");
+
+// not thread safe, so only call on main thread
+//static
+void TimeBlock::processTimes()
+{
+ LLFastTimer _(FTM_PROCESS_TIMES);
+ get_clock_count(); // good place to calculate clock frequency
+
+ // set up initial tree
+ bootstrapTimerTree();
+
+ incrementalUpdateTimerTree();
+
+ updateTimes();
// reset for next frame
for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(),
@@ -288,14 +308,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 +337,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 +384,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 +399,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 +468,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..e800befd9f 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:
@@ -115,6 +115,7 @@ public:
static void pushLog(LLSD sd);
static void setLogLock(LLMutex* mutex);
static void writeLog(std::ostream& os);
+ static void updateTimes();
// dumps current cumulative frame stats to log
// call nextFrame() to reset timers
@@ -262,6 +263,9 @@ public:
// can be called multiple times in a frame, at any point
static void processTimes();
+ static void bootstrapTimerTree();
+ static void incrementalUpdateTimerTree();
+
// call this once a frame to periodically log timers
static void logStats();
diff --git a/indra/llcommon/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.h b/indra/llcommon/lltrace.h
index cfe1273b4b..6292534a03 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
@@ -672,7 +687,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 +709,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 +731,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 +754,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 +779,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..ef24ba21ee 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -296,7 +296,7 @@ LLPumpIO* gServicePump = NULL;
U64 gFrameTime = 0;
F32 gFrameTimeSeconds = 0.f;
-LLUnit<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
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/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 40526d3357..1355b58f8b 100755
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -30,12 +30,14 @@
#include "llviewerwindow.h"
#include "llrect.h"
+#include "llcombobox.h"
#include "llerror.h"
#include "llgl.h"
#include "llimagepng.h"
#include "llrender.h"
#include "llrendertarget.h"
#include "lllocalcliprect.h"
+#include "lllayoutstack.h"
#include "llmath.h"
#include "llfontgl.h"
#include "llsdserialize.h"
@@ -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"));
@@ -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())
{
@@ -219,26 +210,6 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
//left click drills down by expanding timers
mHoverTimer->setCollapsed(false);
}
- else if (mask & MASK_ALT)
- {
- if (mask & MASK_CONTROL)
- {
- mDisplayHz = !mDisplayHz;
- }
- else
- {
- mDisplayCalls = !mDisplayCalls;
- }
- }
- else if (mask & MASK_SHIFT)
- {
- if (++mDisplayMode > 3)
- mDisplayMode = 0;
- }
- else if (mask & MASK_CONTROL)
- {
- mDisplayCenter = (ChildAlignment)((mDisplayCenter + 1) % ALIGN_COUNT);
- }
else if (mGraphRect.pointInRect(x, y))
{
gFocusMgr.setMouseCapture(this);
@@ -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->getCollapsed())
{
- // 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,7 +369,7 @@ BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
setPauseState(true);
mScrollIndex = llclamp( mScrollIndex + clicks,
0,
- llmin((S32)mRecording->getNumPeriods(), (S32)mRecording->getNumPeriods() - MAX_VISIBLE_HISTORY));
+ llmin((S32)mRecording.getNumRecordedPeriods(), (S32)mRecording.getNumRecordedPeriods() - MAX_VISIBLE_HISTORY));
return TRUE;
}
@@ -389,39 +377,73 @@ static TimeBlock FTM_RENDER_TIMER("Timers", true);
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;
@@ -974,16 +996,16 @@ 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());
@@ -993,7 +1015,7 @@ void LLFastTimerView::printLineStats()
}
}
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);
}
@@ -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;
@@ -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->getCollapsed();
+
+ 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/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>