SH-4433 WIP Interesting: Statistics > Ping Sim is always 0 ms

made getPrimaryAccumulator return a reference since it was an
always non-null pointer
changed unit conversion to perform lazy division in order to avoid truncation
of timer values
master
Richard Linden 2013-08-21 14:06:57 -07:00
parent 6d9af37406
commit 2c6bc5afa5
17 changed files with 297 additions and 304 deletions

View File

@ -346,6 +346,8 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
#define LL_INFOS(...) lllog(LLError::LEVEL_INFO, false, ##__VA_ARGS__)
#define LL_WARNS(...) lllog(LLError::LEVEL_WARN, false, ##__VA_ARGS__)
#define LL_ERRS(...) lllog(LLError::LEVEL_ERROR, false, ##__VA_ARGS__)
// alternative to llassert_always that prints explanatory message
#define LL_ERRS_IF(exp, ...) if (exp) LL_ERRS(##__VA_ARGS__) << "(" #exp ")"
// Only print the log message once (good for warnings or infos that would otherwise
// spam the log file over and over, such as tighter loops).

View File

@ -189,15 +189,15 @@ void TimeBlock::bootstrapTimerTree()
// when this timer was called
if (timer.getParent() == &TimeBlock::getRootTimeBlock())
{
TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
if (accumulator->mLastCaller)
if (accumulator.mLastCaller)
{
timer.setParent(accumulator->mLastCaller);
accumulator->mParent = accumulator->mLastCaller;
timer.setParent(accumulator.mLastCaller);
accumulator.mParent = accumulator.mLastCaller;
}
// no need to push up tree on first use, flag can be set spuriously
accumulator->mMoveUpTree = false;
accumulator.mMoveUpTree = false;
}
}
}
@ -223,17 +223,17 @@ void TimeBlock::incrementalUpdateTimerTree()
// skip root timer
if (timerp != &TimeBlock::getRootTimeBlock())
{
TimeBlockAccumulator* accumulator = timerp->getPrimaryAccumulator();
TimeBlockAccumulator& accumulator = timerp->getPrimaryAccumulator();
if (accumulator->mMoveUpTree)
if (accumulator.mMoveUpTree)
{
// since ancestors have already been visited, re-parenting won't affect tree traversal
//step up tree, bringing our descendants with us
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
@ -253,7 +253,7 @@ void TimeBlock::updateTimes()
U64 cur_time = getCPUClockCount64();
BlockTimer* cur_timer = stack_record->mActiveTimer;
TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
TimeBlockAccumulator* accumulator = &stack_record->mTimeBlock->getPrimaryAccumulator();
while(cur_timer
&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
@ -269,7 +269,7 @@ void TimeBlock::updateTimes()
cur_timer->mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
stack_record = &cur_timer->mParentTimerData;
accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
accumulator = &stack_record->mTimeBlock->getPrimaryAccumulator();
cur_timer = stack_record->mActiveTimer;
stack_record->mChildTime += cumulative_time_delta;
@ -299,10 +299,10 @@ void TimeBlock::processTimes()
++it)
{
TimeBlock& timer = *it;
TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
accumulator->mLastCaller = NULL;
accumulator->mMoveUpTree = false;
accumulator.mLastCaller = NULL;
accumulator.mMoveUpTree = false;
}
}

View File

@ -257,11 +257,11 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
#if FAST_TIMER_ON
BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
if (!cur_timer_data) return;
TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
accumulator->mActiveCount++;
mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
accumulator.mActiveCount++;
mBlockStartTotalTimeCounter = accumulator.mTotalTimeCounter;
// keep current parent as long as it is active when we are
accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
accumulator.mMoveUpTree |= (accumulator.mParent->getPrimaryAccumulator().mActiveCount == 0);
// store top of stack
mParentTimerData = *cur_timer_data;
@ -281,16 +281,16 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
if (!cur_timer_data) return;
TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
TimeBlockAccumulator& accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
accumulator->mCalls++;
accumulator->mTotalTimeCounter += total_time - (accumulator->mTotalTimeCounter - mBlockStartTotalTimeCounter);
accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
accumulator->mActiveCount--;
accumulator.mCalls++;
accumulator.mTotalTimeCounter += total_time - (accumulator.mTotalTimeCounter - mBlockStartTotalTimeCounter);
accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
accumulator.mActiveCount--;
// store last caller to bootstrap tree creation
// do this in the destructor in case of recursion to get topmost caller
accumulator->mLastCaller = mParentTimerData.mTimeBlock;
accumulator.mLastCaller = mParentTimerData.mTimeBlock;
// we are only tracking self time, so subtract our total time delta from parents
mParentTimerData.mChildTime += total_time;

View File

@ -130,7 +130,7 @@ void LLMemory::updateMemoryInfo()
}
#else
//not valid for other systems for now.
sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
sAllocatedMemInKB = (U32Bytes)LLMemory::getCurrentRSS();
sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ;
sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;
#endif

View File

@ -55,11 +55,6 @@ const F64 USEC_TO_SEC_F64 = 0.000001;
S32 gUTCOffset = 0; // viewer's offset from server UTC, in seconds
LLTimer* LLTimer::sTimer = NULL;
F64 gClockFrequency = 0.0;
F64 gClockFrequencyInv = 0.0;
F64 gClocksToMicroseconds = 0.0;
U64 gTotalTimeClockCount = 0;
U64 gLastTotalTimeClockCount = 0;
//
// Forward declarations
@ -213,56 +208,76 @@ U64 get_clock_count()
#endif
void update_clock_frequencies()
struct TimerInfo
{
gClockFrequency = calc_clock_frequency(50U);
gClockFrequencyInv = 1.0/gClockFrequency;
gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC;
}
TimerInfo()
: mClockFrequency(0.0),
mTotalTimeClockCount(0),
mLastTotalTimeClockCount(0)
{}
void update()
{
mClockFrequency = calc_clock_frequency(50U);
mClockFrequencyInv = 1.0/mClockFrequency;
mClocksToMicroseconds = mClockFrequencyInv;
}
F64 mClockFrequency;
F64SecondsImplicit mClockFrequencyInv;
F64MicrosecondsImplicit mClocksToMicroseconds;
U64 mTotalTimeClockCount;
U64 mLastTotalTimeClockCount;
};
TimerInfo& get_timer_info()
{
static TimerInfo sTimerInfo;
return sTimerInfo;
}
///////////////////////////////////////////////////////////////////////////////
// returns a U64 number that represents the number of
// microseconds since the unix epoch - Jan 1, 1970
// microseconds since the Unix epoch - Jan 1, 1970
U64MicrosecondsImplicit totalTime()
{
U64 current_clock_count = get_clock_count();
if (!gTotalTimeClockCount)
if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0)
{
update_clock_frequencies();
gTotalTimeClockCount = current_clock_count;
get_timer_info().update();
get_timer_info().mTotalTimeClockCount = current_clock_count;
#if LL_WINDOWS
// Synch us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
// Sync us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
// Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to
// make in the future.
gTotalTimeClockCount = (U64)(time(NULL) * gClockFrequency);
get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency);
#endif
// Update the last clock count
gLastTotalTimeClockCount = current_clock_count;
get_timer_info().mLastTotalTimeClockCount = current_clock_count;
}
else
{
if (current_clock_count >= gLastTotalTimeClockCount)
if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount)
{
// No wrapping, we're all okay.
gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount;
get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount;
}
else
{
// We've wrapped. Compensate correctly
gTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - gLastTotalTimeClockCount) + current_clock_count;
get_timer_info().mTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - get_timer_info().mLastTotalTimeClockCount) + current_clock_count;
}
// Update the last clock count
gLastTotalTimeClockCount = current_clock_count;
get_timer_info().mLastTotalTimeClockCount = current_clock_count;
}
// Return the total clock tick count in microseconds.
return U64Microseconds(gTotalTimeClockCount*gClocksToMicroseconds);
U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds);
return time;
}
@ -270,9 +285,9 @@ U64MicrosecondsImplicit totalTime()
LLTimer::LLTimer()
{
if (!gClockFrequency)
if (!get_timer_info().mClockFrequency)
{
update_clock_frequencies();
get_timer_info().update();
}
mStarted = TRUE;
@ -298,13 +313,14 @@ void LLTimer::cleanupClass()
U64MicrosecondsImplicit LLTimer::getTotalTime()
{
// simply call into the implementation function.
return totalTime();
U64MicrosecondsImplicit total_time = totalTime();
return total_time;
}
// static
F64SecondsImplicit LLTimer::getTotalSeconds()
{
return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
return F64Microseconds(U64_to_F64(getTotalTime()));
}
void LLTimer::reset()
@ -354,7 +370,7 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
F64SecondsImplicit LLTimer::getElapsedTimeF64() const
{
U64 last = mLastClockCount;
return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv;
}
F32SecondsImplicit LLTimer::getElapsedTimeF32() const
@ -364,7 +380,7 @@ F32SecondsImplicit LLTimer::getElapsedTimeF32() const
F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64()
{
return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv;
}
F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
@ -377,7 +393,7 @@ F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)
{
mExpirationTicks = get_clock_count()
+ (U64)((F32)(expiration * gClockFrequency));
+ (U64)((F32)(expiration * get_timer_info().mClockFrequency));
}
F32SecondsImplicit LLTimer::getRemainingTimeF32() const
@ -387,7 +403,7 @@ F32SecondsImplicit LLTimer::getRemainingTimeF32() const
{
return 0.0f;
}
return F32((mExpirationTicks - cur_ticks) * gClockFrequencyInv);
return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv);
}
@ -400,7 +416,7 @@ BOOL LLTimer::checkExpirationAndReset(F32 expiration)
}
mExpirationTicks = cur_ticks
+ (U64)((F32)(expiration * gClockFrequency));
+ (U64)((F32)(expiration * get_timer_info().mClockFrequency));
return TRUE;
}
@ -499,20 +515,20 @@ BOOL is_daylight_savings()
struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
{
S32 pacific_offset_hours;
S32Hours pacific_offset_hours;
if (pacific_daylight_time)
{
pacific_offset_hours = 7;
pacific_offset_hours = S32Hours(7);
}
else
{
pacific_offset_hours = 8;
pacific_offset_hours = S32Hours(8);
}
// We subtract off the PST/PDT offset _before_ getting
// "UTC" time, because this will handle wrapping around
// for 5 AM UTC -> 10 PM PDT of the previous day.
utc_time -= pacific_offset_hours * MIN_PER_HOUR * SEC_PER_MIN;
utc_time -= S32SecondsImplicit(pacific_offset_hours);
// Internal buffer to PST/PDT (see above)
struct tm* internal_time = gmtime(&utc_time);
@ -529,7 +545,7 @@ struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
}
void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring)
{
U64 hours;
U64 minutes;
@ -551,9 +567,9 @@ void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
}
void secondsToTimecodeString(F32 current_time, std::string& tcstring)
void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring)
{
microsecondsToTimecodeString((U64)((F64)(SEC_TO_MICROSEC*current_time)), tcstring);
microsecondsToTimecodeString(current_time, tcstring);
}

View File

@ -168,8 +168,8 @@ LL_COMMON_API BOOL is_daylight_savings();
// struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight);
LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
LL_COMMON_API void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring);
LL_COMMON_API void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring);
U64MicrosecondsImplicit LL_COMMON_API totalTime(); // Returns current system time in microseconds

View File

@ -76,7 +76,7 @@ void TimeBlockTreeNode::setParent( TimeBlock* parent )
}
mParent = parent;
mBlock->getPrimaryAccumulator()->mParent = parent;
mBlock->getPrimaryAccumulator().mParent = parent;
parent_tree_node->mChildren.push_back(mBlock);
parent_tree_node->mNeedsSorting = true;
}

View File

@ -80,10 +80,10 @@ public:
mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
{}
LL_FORCE_INLINE ACCUMULATOR* getPrimaryAccumulator() const
LL_FORCE_INLINE ACCUMULATOR& getPrimaryAccumulator() const
{
ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage();
return &accumulator_storage[mAccumulatorIndex];
return accumulator_storage[mAccumulatorIndex];
}
size_t getIndex() const { return mAccumulatorIndex; }
@ -137,7 +137,7 @@ template<typename T, typename VALUE_T>
void record(EventStatHandle<T>& measurement, VALUE_T value)
{
T converted_value(value);
measurement.getPrimaryAccumulator()->record(storage_value(converted_value));
measurement.getPrimaryAccumulator().record(storage_value(converted_value));
}
template <typename T = F64>
@ -160,7 +160,7 @@ template<typename T, typename VALUE_T>
void sample(SampleStatHandle<T>& measurement, VALUE_T value)
{
T converted_value(value);
measurement.getPrimaryAccumulator()->sample(storage_value(converted_value));
measurement.getPrimaryAccumulator().sample(storage_value(converted_value));
}
template <typename T = F64>
@ -183,7 +183,7 @@ template<typename T, typename VALUE_T>
void add(CountStatHandle<T>& count, VALUE_T value)
{
T converted_value(value);
count.getPrimaryAccumulator()->add(storage_value(converted_value));
count.getPrimaryAccumulator().add(storage_value(converted_value));
}
template<>
@ -340,49 +340,37 @@ public:
void* operator new(size_t size)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
accumulator->mAllocatedCount++;
}
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
accumulator.mAllocatedCount++;
return ::operator new(size);
}
void operator delete(void* ptr, size_t size)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
accumulator->mAllocatedCount--;
accumulator->mDeallocatedCount++;
}
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
accumulator.mAllocatedCount--;
accumulator.mDeallocatedCount++;
::operator delete(ptr);
}
void *operator new [](size_t size)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
accumulator->mAllocatedCount++;
}
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
accumulator.mAllocatedCount++;
return ::operator new[](size);
}
void operator delete[](void* ptr, size_t size)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
accumulator->mAllocatedCount--;
accumulator->mDeallocatedCount++;
}
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
accumulator.mAllocatedCount--;
accumulator.mDeallocatedCount++;
::operator delete[](ptr);
}
@ -405,12 +393,9 @@ public:
template<typename AMOUNT_T>
AMOUNT_T& memClaimAmount(AMOUNT_T& size)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
mMemFootprint += (size_t)size;
if (accumulator)
{
accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
}
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
return size;
}
@ -432,11 +417,8 @@ public:
template<typename AMOUNT_T>
AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
}
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
return size;
}
@ -448,24 +430,18 @@ private:
{
static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
size_t footprint = MemFootprint<TRACKED>::measure(tracked);
accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)footprint);
tracker.mMemFootprint += footprint;
}
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
size_t footprint = MemFootprint<TRACKED>::measure(tracked);
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)footprint : (F64)footprint);
tracker.mMemFootprint += footprint;
}
static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
size_t footprint = MemFootprint<TRACKED>::measure(tracked);
accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)footprint);
tracker.mMemFootprint -= footprint;
}
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
size_t footprint = MemFootprint<TRACKED>::measure(tracked);
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)footprint : -(F64)footprint);
tracker.mMemFootprint -= footprint;
}
};
@ -474,20 +450,14 @@ private:
{
static void claim(mem_trackable_t& tracker, TRACKED& tracked)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked));
}
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked) : (F64)MemFootprint<TRACKED>::measure(tracked));
}
static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
{
MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
if (accumulator)
{
accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked));
}
MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked) : -(F64)MemFootprint<TRACKED>::measure(tracked));
}
};
};

View File

@ -114,10 +114,13 @@ void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
void AccumulatorBufferGroup::sync()
{
F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
if (isPrimary())
{
F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
mSamples.sync(time_stamp);
mMemStats.sync(time_stamp);
mSamples.sync(time_stamp);
mMemStats.sync(time_stamp);
}
}
void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type )
@ -144,6 +147,7 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
if (other.mTotalSamplingTime > epsilon)
{
llassert(mTotalSamplingTime > 0);
// combine variance (and hence standard deviation) of 2 different sized sample groups using
// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
F64 n_1 = mTotalSamplingTime,
@ -166,17 +170,16 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
/ (n_1 + n_2 - epsilon));
}
llassert(other.mTotalSamplingTime > 0);
F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
mNumSamples += other.mNumSamples;
mTotalSamplingTime += other.mTotalSamplingTime;
mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
llassert(mMean < 0 || mMean >= 0);
}
if (append_type == SEQUENTIAL)
{
mLastValue = other.mLastValue;
mLastSampleTimeStamp = other.mLastSampleTimeStamp;
mHasValue = true;
}
}
}
@ -190,6 +193,7 @@ void SampleAccumulator::reset( const SampleAccumulator* other )
mMin = mLastValue;
mMax = mLastValue;
mMean = mLastValue;
LL_ERRS_IF(mHasValue && !(mMean < 0) && !(mMean >= 0)) << "Invalid mean after capturing value" << LL_ENDL;
mSumOfSquares = 0;
mLastSampleTimeStamp = LLTimer::getTotalSeconds();
mTotalSamplingTime = 0;

View File

@ -1,3 +1,4 @@
/**
* @file lltraceaccumulators.h
* @brief Storage for accumulating statistics
@ -317,6 +318,7 @@ namespace LLTrace
mMin = value;
mMax = value;
mMean = value;
llassert(mMean < 0 || mMean >= 0);
mLastSampleTimeStamp = time_stamp;
}
else
@ -341,6 +343,7 @@ namespace LLTrace
mTotalSamplingTime += delta_time;
F64 old_mean = mMean;
mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
llassert(mMean < 0 || mMean >= 0);
mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
}
mLastSampleTimeStamp = time_stamp;

View File

@ -69,13 +69,13 @@ void ThreadRecorder::init()
tree_node.mBlock = &time_block;
tree_node.mParent = &root_time_block;
it->getPrimaryAccumulator()->mParent = &root_time_block;
it->getPrimaryAccumulator().mParent = &root_time_block;
}
mRootTimer = new BlockTimer(root_time_block);
timer_stack->mActiveTimer = mRootTimer;
TimeBlock::getRootTimeBlock().getPrimaryAccumulator()->mActiveCount = 1;
TimeBlock::getRootTimeBlock().getPrimaryAccumulator().mActiveCount = 1;
}
@ -247,8 +247,6 @@ void ThreadRecorder::pushToParent()
mThreadRecordingBuffers.reset();
}
}
static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data");

View File

@ -156,7 +156,8 @@ struct LLUnit
static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v)
{
self_t result;
ll_convert_units(v, result);
STORAGE_TYPE divisor = ll_convert_units(v, result);
result.mValue /= divisor;
return result;
}
@ -193,7 +194,7 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
template<typename OTHER_STORAGE, typename OTHER_UNIT>
LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
: base_t(convert(other))
: base_t(other)
{}
// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
@ -209,6 +210,8 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
base_t::mValue += value;
}
// this overload exists to explicitly catch use of another implicit unit
// without ambiguity between conversion to storage_t vs conversion to base_t
template<typename OTHER_STORAGE, typename OTHER_UNIT>
void operator += (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
{
@ -221,6 +224,8 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
base_t::mValue -= value;
}
// this overload exists to explicitly catch use of another implicit unit
// without ambiguity between conversion to storage_t vs conversion to base_t
template<typename OTHER_STORAGE, typename OTHER_UNIT>
void operator -= (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
{
@ -246,35 +251,35 @@ std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYP
}
template<typename S1, typename T1, typename S2, typename T2>
LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...)
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...)
{
S2 divisor(1);
LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value
|| !LLIsSameType<T1, typename T1::base_unit_t>::value
|| !LLIsSameType<T2, typename T2::base_unit_t>::value), "invalid conversion: incompatible units");
|| !LLIsSameType<T1, typename T1::base_unit_t>::value
|| !LLIsSameType<T2, typename T2::base_unit_t>::value),
"conversion requires compatible units");
if (LLIsSameType<T1, typename T1::base_unit_t>::value)
if (LLIsSameType<T1, T2>::value)
{
if (LLIsSameType<T2, typename T2::base_unit_t>::value)
{
// T1 and T2 fully reduced and equal...just copy
out = LLUnit<S2, T2>((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);
}
// T1 and T2 same type, just assign
out.value((S2)in.value());
}
else if (LLIsSameType<T2, typename T2::base_unit_t>::value)
{
// reduce T1
LLUnit<S2, typename T1::base_unit_t> new_in;
divisor *= (S2)ll_convert_units(in, new_in);
divisor *= (S2)ll_convert_units(new_in, 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);
// reduce T2
LLUnit<S2, typename T2::base_unit_t> new_out;
divisor *= (S2)ll_convert_units(in, new_out);
divisor *= (S2)ll_convert_units(new_out, out);
}
return divisor;
}
template<typename T>
@ -579,77 +584,86 @@ struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
static const char* getUnitLabel() { return T::getUnitLabel(); }
};
template<typename INPUT_TYPE, typename OUTPUT_TYPE>
template<typename T>
struct LLUnitLinearOps
{
typedef LLUnitLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t;
typedef LLUnitLinearOps<T> self_t;
LLUnitLinearOps(INPUT_TYPE val)
: mInput (val)
LLUnitLinearOps(T val)
: mValue(val),
mDivisor(1)
{}
operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; }
INPUT_TYPE mInput;
T mValue;
T mDivisor;
template<typename T>
output_t operator * (T other)
template<typename OTHER_T>
self_t operator * (OTHER_T other)
{
return typename LLResultTypeMultiply<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
return mValue * other;
}
template<typename T>
output_t operator / (T other)
template<typename OTHER_T>
self_t operator / (OTHER_T other)
{
return typename LLResultTypeDivide<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
mDivisor *= other;
return *this;
}
template<typename T>
output_t operator + (T other)
template<typename OTHER_T>
self_t operator + (OTHER_T other)
{
return typename LLResultTypeAdd<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
mValue += other;
return *this;
}
template<typename T>
output_t operator - (T other)
template<typename OTHER_T>
self_t operator - (OTHER_T other)
{
return typename LLResultTypeSubtract<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
mValue -= other;
return *this;
}
};
template<typename INPUT_TYPE, typename OUTPUT_TYPE>
template<typename T>
struct LLUnitInverseLinearOps
{
typedef LLUnitInverseLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t;
typedef LLUnitInverseLinearOps<T> self_t;
LLUnitInverseLinearOps(INPUT_TYPE val)
: mInput(val)
LLUnitInverseLinearOps(T val)
: mValue(val),
mDivisor(1)
{}
operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; }
INPUT_TYPE mInput;
T mValue;
T mDivisor;
template<typename T>
output_t operator * (T other)
template<typename OTHER_T>
self_t operator * (OTHER_T other)
{
return typename LLResultTypeDivide<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
mDivisor *= other;
return *this;
}
template<typename T>
output_t operator / (T other)
template<typename OTHER_T>
self_t operator / (OTHER_T other)
{
return typename LLResultTypeMultiply<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
mValue *= other;
return *this;
}
template<typename T>
output_t operator + (T other)
template<typename OTHER_T>
self_t operator + (OTHER_T other)
{
return typename LLResultTypeAdd<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
mValue -= other;
return *this;
}
template<typename T>
output_t operator - (T other)
template<typename OTHER_T>
self_t operator - (OTHER_T other)
{
return typename LLResultTypeSubtract<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
mValue += other;
return *this;
}
};
@ -666,28 +680,32 @@ struct base_unit_name
}
#define LL_DECLARE_DERIVED_UNIT(base_unit_name, conversion_operation, unit_name, unit_label) \
struct unit_name \
{ \
typedef base_unit_name base_unit_t; \
static const char* getUnitLabel() { return unit_label; } \
template<typename T> \
static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); } \
template<typename STORAGE_T, typename UNIT_T> \
static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
{ return LLUnit<STORAGE_T, unit_name>(value); } \
}; \
\
template<typename S1, typename S2> \
void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \
{ \
out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1, S2>(in.value()) conversion_operation)); \
} \
\
template<typename S1, typename S2> \
void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \
{ \
out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1, S2>(in.value()) conversion_operation)); \
#define LL_DECLARE_DERIVED_UNIT(base_unit_name, conversion_operation, unit_name, unit_label) \
struct unit_name \
{ \
typedef base_unit_name base_unit_t; \
static const char* getUnitLabel() { return unit_label; } \
template<typename T> \
static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); } \
template<typename STORAGE_T, typename UNIT_T> \
static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
{ return LLUnit<STORAGE_T, unit_name>(value); } \
}; \
\
template<typename S1, typename S2> \
S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \
{ \
LLUnitLinearOps<S2> op = LLUnitLinearOps<S2>(in.value()) conversion_operation; \
out = LLUnit<S2, base_unit_name>((S2)op.mValue); \
return op.mDivisor; \
} \
\
template<typename S1, typename S2> \
S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \
{ \
LLUnitInverseLinearOps<S2> op = LLUnitInverseLinearOps<S2>(in.value()) conversion_operation; \
out = LLUnit<S2, unit_name>((S2)op.mValue); \
return op.mDivisor; \
}
#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name) \

View File

@ -38,12 +38,9 @@ namespace LLUnits
LL_DECLARE_DERIVED_UNIT(Latinum, / 16, Solari, "Sol");
}
typedef LLUnit<F32, LLUnits::Quatloos> F32Quatloos;
typedef LLUnit<S32, LLUnits::Quatloos> S32Quatloos;
typedef LLUnit<F32, LLUnits::Latinum> F32Latinum;
typedef LLUnit<S32, LLUnits::Latinum> S32Latinum;
typedef LLUnit<F32, LLUnits::Solari> F32Solari;
typedef LLUnit<S32, LLUnits::Solari> S32Solari;
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Quatloos);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Latinum);
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Solari);
namespace tut
{
@ -83,6 +80,15 @@ namespace tut
LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos);
ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == S32Quatloos(42));
S32Solari int_solari(1);
float_quatloos = int_solari;
ensure("fractional units are preserved in conversion from integer to float type", float_quatloos == F32Quatloos(0.25f));
int_quatloos = S32Quatloos(1);
F32Solari float_solari = int_quatloos;
ensure("can convert with fractional intermediates from integer to float type", float_solari == F32Solari(4.f));
}
// conversions to/from base unit
@ -185,6 +191,11 @@ namespace tut
return true;
}
bool accept_implicit_quatloos(S32Quatloos q)
{
return true;
}
// signature compatibility
template<> template<>
void units_object_t::test<6>()

View File

@ -386,17 +386,24 @@ void LLStatBar::draw()
mCurMaxBar = LLSmoothInterpolation::lerp(mCurMaxBar, mMaxBar, 0.05f);
mCurMinBar = LLSmoothInterpolation::lerp(mCurMinBar, mMinBar, 0.05f);
// rate limited updates
if (mLastDisplayValueTimer.getElapsedTimeF32() > MEAN_VALUE_UPDATE_TIME)
S32 decimal_digits = mDecimalDigits;
if (is_approx_equal((F32)(S32)display_value, display_value))
{
mLastDisplayValueTimer.reset();
drawLabelAndValue(display_value, unit_label, bar_rect);
mLastDisplayValue = display_value;
decimal_digits = 0;
}
// rate limited updates
if (mLastDisplayValueTimer.getElapsedTimeF32() < MEAN_VALUE_UPDATE_TIME)
{
display_value = mLastDisplayValue;
}
else
{
drawLabelAndValue(mLastDisplayValue, unit_label, bar_rect);
mLastDisplayValueTimer.reset();
}
drawLabelAndValue(display_value, unit_label, bar_rect, mDecimalDigits);
mLastDisplayValue = display_value;
if (mDisplayBar
&& (mCountFloatp || mEventFloatp || mSampleFloatp))
@ -568,16 +575,11 @@ LLRect LLStatBar::getRequiredRect()
return rect;
}
void LLStatBar::drawLabelAndValue( F32 value, std::string &label, LLRect &bar_rect )
void LLStatBar::drawLabelAndValue( F32 value, std::string &label, LLRect &bar_rect, S32 decimal_digits )
{
LLFontGL::getFontMonospace()->renderUTF8(mLabel, 0, 0, getRect().getHeight(), LLColor4(1.f, 1.f, 1.f, 1.f),
LLFontGL::LEFT, LLFontGL::TOP);
S32 decimal_digits = mDecimalDigits;
if (is_approx_equal((F32)(S32)value, value))
{
decimal_digits = 0;
}
std::string value_str = !llisnan(value)
? llformat("%10.*f %s", decimal_digits, value, label.c_str())
: "n/a";

View File

@ -72,7 +72,7 @@ public:
/*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options.
private:
void drawLabelAndValue( F32 mean, std::string &unit_label, LLRect &bar_rect );
void drawLabelAndValue( F32 mean, std::string &unit_label, LLRect &bar_rect, S32 decimal_digits );
void drawTicks( F32 min, F32 max, F32 value_scale, LLRect &bar_rect );
F32 mMinBar,

View File

@ -2439,7 +2439,7 @@ void LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// Move an object due to idle-time viewer side updates by interpolating motion
void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& time, const F32SecondsImplicit& dt)
void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& time, const F32SecondsImplicit& dt_seconds)
{
// linear motion
// PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object
@ -2450,8 +2450,9 @@ void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& time, con
// to see if object is selected, instead of explicitly
// zeroing it out
F32 dt = dt_seconds;
F64Seconds time_since_last_update = time - mLastMessageUpdateSecs;
if (time_since_last_update <= (F64Seconds)0.0 || dt <= (F32Seconds)0.f)
if (time_since_last_update <= (F64Seconds)0.0 || dt <= 0.f)
{
return;
}
@ -2463,7 +2464,7 @@ void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& time, con
{ // Old code path ... unbounded, simple interpolation
if (!(accel.isExactlyZero() && vel.isExactlyZero()))
{
LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt.value();
LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
// region local
setPositionRegion(pos + getPositionRegion());
@ -2477,7 +2478,7 @@ void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& time, con
{ // Object is moving, and hasn't been too long since we got an update from the server
// Calculate predicted position and velocity
LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt.value();
LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
LLVector3 new_v = accel * dt;
if (time_since_last_update > sPhaseOutUpdateInterpolationTime &&

View File

@ -42,8 +42,7 @@
show_bar="true"/>
<stat_bar name="packet_loss"
label="Packet Loss"
stat="packetslostpercentstat"
decimal_digits="3"/>
stat="packetslostpercentstat"/>
<stat_bar name="ping"
label="Ping Sim"
stat="simpingstat"/>
@ -71,12 +70,10 @@
stat="numobjectsstat"/>
<stat_bar name="newobjs"
label="New Objects"
stat="numnewobjectsstat"
bar_max="2000"/>
stat="numnewobjectsstat"/>
<stat_bar name="object_cache_hits"
label="Object Cache Hit Rate"
stat="object_cache_hits"
bar_max="100"
show_history="true"/>
</stat_view>
<stat_view name="texture"
@ -86,7 +83,6 @@
<stat_bar name="texture_cache_hits"
label="Cache Hit Rate"
stat="texture_cache_hits"
bar_max="100"
show_history="true"/>
<stat_bar name="texture_cache_read_latency"
label="Cache Read Latency"
@ -100,20 +96,16 @@
stat="numrawimagesstat"/>
<stat_bar name="gltexmemstat"
label="GL Mem"
stat="gltexmemstat"
decimal_digits="1"/>
stat="gltexmemstat"/>
<stat_bar name="formattedmemstat"
label="Formatted Mem"
stat="formattedmemstat"
decimal_digits="3"/>
stat="formattedmemstat"/>
<stat_bar name="rawmemstat"
label="Raw Mem"
stat="rawmemstat"
decimal_digits="3"/>
stat="rawmemstat"/>
<stat_bar name="glboundmemstat"
label="Bound Mem"
stat="glboundmemstat"
decimal_digits="3"/>
stat="glboundmemstat"/>
</stat_view>
<stat_view name="network"
@ -168,9 +160,7 @@
setting="OpenDebugStatSim">
<stat_bar name="simtimedilation"
label="Time Dilation"
stat="simtimedilation"
decimal_digits="3"
bar_max="1" />
stat="simtimedilation"/>
<stat_bar name="simfps"
label="Sim FPS"
stat="simfps"
@ -202,28 +192,22 @@
decimal_digits="1"/>
<stat_bar name="simmainagents"
label="Main Agents"
stat="simmainagents"
bar_max="80"/>
stat="simmainagents"/>
<stat_bar name="simchildagents"
label="Child Agents"
stat="simchildagents"/>
<stat_bar name="simobjects"
label="Objects"
stat="simobjects"
bar_max="30000" />
stat="simobjects"/>
<stat_bar name="simactiveobjects"
label="Active Objects"
stat="simactiveobjects"
bar_max="5000"/>
stat="simactiveobjects"/>
<stat_bar name="simactivescripts"
label="Active Scripts"
stat="simactivescripts"
bar_max="15000"/>
stat="simactivescripts"/>
<stat_bar name="simpctscriptsrun"
label="Scripts Run"
stat="simpctscriptsrun"
bar_max="100"
decimal_digits="3"/>
stat="simpctscriptsrun"/>
<stat_bar name="simscripteps"
label="Script Events"
stat="simscripteps"
@ -234,16 +218,13 @@
show_label="true">
<stat_bar name="simsimaistepmsec"
label="AI Step Time"
stat="simsimaistepmsec"
decimal_digits="3"/>
stat="simsimaistepmsec"/>
<stat_bar name="simsimskippedsilhouettesteps"
label="Skipped Silhouette Steps"
stat="simsimskippedsilhouettesteps"
unit_label="/sec"
bar_max="45"/>
unit_label="/sec"/>
<stat_bar name="simsimpctsteppedcharacters"
stat="simsimpctsteppedcharacters"
bar_max="100"
decimal_digits="1"/>
</stat_view>
<stat_bar name="siminpps"
@ -261,7 +242,7 @@
label="Pending Uploads"
stat="simpendinguploads"/>
<stat_bar name="simtotalunackedbytes"
label="Total Unacked Bytes"
label="Total Unacked Data"
stat="simtotalunackedbytes"
decimal_digits="1"/>
<stat_view name="simperf"
@ -270,60 +251,47 @@
show_label="true">
<stat_bar name="simframemsec"
label="Total Frame Time"
stat="simframemsec"
decimal_digits="3"/>
stat="simframemsec"/>
<stat_bar name="simnetmsec"
label="Net Time"
stat="simnetmsec"
decimal_digits="3"/>
stat="simnetmsec"/>
<stat_bar name="simsimphysicsmsec"
label="Physics Time"
stat="simsimphysicsmsec"
decimal_digits="3"/>
stat="simsimphysicsmsec"/>
<stat_bar name="simsimothermsec"
label="Simulation Time"
stat="simsimothermsec"
decimal_digits="3"/>
stat="simsimothermsec"/>
<stat_bar name="simagentmsec"
label="Agent Time"
stat="simagentmsec"
decimal_digits="3"/>
stat="simagentmsec"/>
<stat_bar name="simimagesmsec"
label="Images Time"
stat="simimagesmsec"
decimal_digits="3"/>
stat="simimagesmsec"/>
<stat_bar name="simscriptmsec"
label="Script Time"
stat="simscriptmsec"
decimal_digits="3"/>
stat="simscriptmsec"/>
<stat_bar name="simsparemsec"
label="Spare Time"
stat="simsparemsec"
decimal_digits="3"/>
stat="simsparemsec"/>
<stat_view name="timedetails"
label="Time Details"
follows="left|top|right"
show_label="true">
<stat_bar name="simsimphysicsstepmsec"
label="Physics Step"
stat="simsimphysicsstepmsec"
decimal_digits="3"/>
stat="simsimphysicsstepmsec"/>
<stat_bar name="simsimphysicsshapeupdatemsec"
label="Update Phys Shapes"
stat="simsimphysicsshapeupdatemsec"
decimal_digits="3"/>
stat="simsimphysicsshapeupdatemsec"/>
<stat_bar name="simsimphysicsothermsec"
label="Physics Other"
stat="simsimphysicsothermsec"
decimal_digits="3"/>
stat="simsimphysicsothermsec"/>
<stat_bar name="simsleepmsec"
label="Sleep Time"
stat="simsleepmsec"
decimal_digits="3"/>
stat="simsleepmsec"/>
<stat_bar name="simpumpiomsec"
label="Pump IO"
stat="simpumpiomsec"
decimal_digits="3"/>
stat="simpumpiomsec"/>
</stat_view>
</stat_view>
</stat_view>