diff options
author | Richard Linden <none@none> | 2013-06-18 23:41:53 -0700 |
---|---|---|
committer | Richard Linden <none@none> | 2013-06-18 23:41:53 -0700 |
commit | d136c4c29686c565b5a46503aa67a9c958b4145d (patch) | |
tree | 6eb0a18df5fc07172332777cf694faad7f8a4796 /indra | |
parent | 1cb0c974ae410479a1f72dab556ef7c9371970ee (diff) |
SH-4246 FIX interesting: fast timers significantly decreases framerate
removed implicit flushes on reads from recorders for better performance
made sure stack timers were updated on recorder deactivate
faster rendering and better ui for fast timer view
Diffstat (limited to 'indra')
-rwxr-xr-x | indra/llcommon/llfasttimer.cpp | 77 | ||||
-rwxr-xr-x | indra/llcommon/llfasttimer.h | 4 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 19 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 38 | ||||
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.cpp | 1 | ||||
-rw-r--r-- | indra/llcommon/tests/llunits_test.cpp | 3 | ||||
-rwxr-xr-x | indra/newview/llfasttimerview.cpp | 316 | ||||
-rwxr-xr-x | indra/newview/llfasttimerview.h | 33 | ||||
-rwxr-xr-x | indra/newview/skins/default/xui/en/floater_fast_timers.xml | 69 |
9 files changed, 315 insertions, 245 deletions
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index d9670891f8..4da9c3fd6c 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -178,43 +178,38 @@ TimeBlockTreeNode& TimeBlock::getTreeNode() const return *nodep; } -static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times"); -// not thread safe, so only call on main thread -//static -void TimeBlock::processTimes() +void TimeBlock::bootstrapTimerTree() { - LLFastTimer _(FTM_PROCESS_TIMES); - get_clock_count(); // good place to calculate clock frequency - U64 cur_time = getCPUClockCount64(); - - // set up initial tree for (LLInstanceTracker<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(); } diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index fdc6997d45..e800befd9f 100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -115,6 +115,7 @@ public: static void pushLog(LLSD sd); static void setLogLock(LLMutex* mutex); static void writeLog(std::ostream& os); + static void updateTimes(); // dumps current cumulative frame stats to log // call nextFrame() to reset timers @@ -262,6 +263,9 @@ public: // can be called multiple times in a frame, at any point static void processTimes(); + static void bootstrapTimerTree(); + static void incrementalUpdateTimerTree(); + // call this once a frame to periodically log timers static void logStats(); diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index cd377531e8..6292534a03 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -157,12 +157,12 @@ public: } } - void flush() + void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) { llassert(mStorageSize >= sNextStorageSlot); for (size_t i = 0; i < sNextStorageSlot; i++) { - mStorage[i].flush(); + mStorage[i].flush(time_stamp); } } @@ -380,7 +380,7 @@ public: mLastValue = other ? other->mLastValue : 0; } - void flush() {} + void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {} F64 getSum() const { return mSum; } F64 getMin() const { return mMin; } @@ -512,9 +512,8 @@ public: mHasValue = other ? other->mHasValue : false; } - void flush() + void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) { - LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds(); LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp; if (mHasValue) @@ -579,7 +578,7 @@ public: mSum = 0; } - void flush() {} + void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {} F64 getSum() const { return mSum; } @@ -614,7 +613,7 @@ public: TimeBlockAccumulator(); void addSamples(const self_t& other, bool /*append*/); void reset(const self_t* other); - void flush() {} + void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {} // // members @@ -780,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 f2c5941011..33002929ea 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -107,7 +107,9 @@ void RecordingBuffers::reset(RecordingBuffers* other) void RecordingBuffers::flush() { - mSamples.flush(); + LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds(); + + mSamples.flush(time_stamp); } /////////////////////////////////////////////////////////////////////// @@ -205,7 +207,6 @@ void Recording::mergeRecording( const Recording& other) 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(); } @@ -213,14 +214,12 @@ LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumul 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; } @@ -228,7 +227,6 @@ LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccu { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; - update(); return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()); } @@ -237,105 +235,88 @@ LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccu { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; - update(); return (F64)(accumulator.mSelfTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()); } F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat) { - update(); return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value(); } LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMin(); } LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMean(); } LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMax(); } LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation(); } LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue(); } LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin(); } LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean(); } LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax(); } LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { - update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation(); } 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.value()) @@ -344,79 +325,66 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat ) 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(); } diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index c1a0700eff..54006f4e5b 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -111,6 +111,7 @@ ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringU if (mActiveRecordings.empty()) return mActiveRecordings.rend(); mActiveRecordings.back()->mPartialRecording.flush(); + TimeBlock::updateTimes(); active_recording_list_t::reverse_iterator it, end_it; for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend(); diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp index 04764f6c2f..a5df51f6de 100644 --- a/indra/llcommon/tests/llunits_test.cpp +++ b/indra/llcommon/tests/llunits_test.cpp @@ -56,6 +56,9 @@ namespace tut LLUnit<F32, Quatloos> float_quatloos; ensure(float_quatloos == 0.f); + LLUnit<F32, Quatloos> float_initialize_quatloos(1); + ensure(float_initialize_quatloos == 1.f); + LLUnit<S32, Quatloos> int_quatloos; ensure(int_quatloos == 0); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 231ece4bbd..1355b58f8b 100755 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -30,12 +30,14 @@ #include "llviewerwindow.h" #include "llrect.h" +#include "llcombobox.h" #include "llerror.h" #include "llgl.h" #include "llimagepng.h" #include "llrender.h" #include "llrendertarget.h" #include "lllocalcliprect.h" +#include "lllayoutstack.h" #include "llmath.h" #include "llfontgl.h" #include "llsdserialize.h" @@ -59,6 +61,8 @@ using namespace LLTrace; static const S32 MAX_VISIBLE_HISTORY = 12; static const S32 LINE_GRAPH_HEIGHT = 240; static const S32 MIN_BAR_HEIGHT = 3; +static const S32 RUNNING_AVERAGE_WIDTH = 100; +static const S32 NUM_FRAMES_HISTORY = 256; std::vector<TimeBlock*> ft_display_idx; // line of table entry for display purposes (for collapse) @@ -95,17 +99,15 @@ LLFastTimerView::LLFastTimerView(const LLSD& key) : LLFloater(key), mHoverTimer(NULL), mDisplayMode(0), - mDisplayCenter(ALIGN_CENTER), - mDisplayCalls(false), - mDisplayHz(false), + mDisplayType(TIME), mScrollIndex(0), mHoverID(NULL), mHoverBarIndex(-1), mStatsIndex(-1), mPauseHistory(false), - mRecording(512) + mRecording(NUM_FRAMES_HISTORY) { - mTimerBarRows.resize(512); + mTimerBarRows.resize(NUM_FRAMES_HISTORY); } LLFastTimerView::~LLFastTimerView() @@ -172,7 +174,7 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) TimeBlock* LLFastTimerView::getLegendID(S32 y) { - S32 idx = (mBarRect.mTop - y) / (LLFontGL::getFontMonospace()->getLineHeight()+2) - 1; + S32 idx = (mLegendRect.mTop - y) / (LLFontGL::getFontMonospace()->getLineHeight() + 2); if (idx >= 0 && idx < (S32)ft_display_idx.size()) { @@ -208,26 +210,6 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) //left click drills down by expanding timers mHoverTimer->setCollapsed(false); } - else if (mask & MASK_ALT) - { - if (mask & MASK_CONTROL) - { - mDisplayHz = !mDisplayHz; - } - else - { - mDisplayCalls = !mDisplayCalls; - } - } - else if (mask & MASK_SHIFT) - { - if (++mDisplayMode > 3) - mDisplayMode = 0; - } - else if (mask & MASK_CONTROL) - { - mDisplayCenter = (ChildAlignment)((mDisplayCenter + 1) % ALIGN_COUNT); - } else if (mGraphRect.pointInRect(x, y)) { gFocusMgr.setMouseCapture(this); @@ -260,7 +242,10 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) if(mPauseHistory && mBarRect.pointInRect(x, y)) { - mHoverBarIndex = llmin((mBarRect.mTop - y) / (mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2)) - 1, + //const S32 bars_top = mBarRect.mTop; + const S32 bars_top = mBarRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4); + + mHoverBarIndex = llmin((bars_top - y) / (mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2)) - 1, (S32)mRecording.getNumRecordedPeriods() - 1, MAX_VISIBLE_HISTORY); if (mHoverBarIndex == 0) @@ -272,25 +257,33 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) mHoverBarIndex = 0; } - TimerBarRow& row = mHoverBarIndex == 0 ? mAverageTimerRow : mTimerBarRows[mHoverBarIndex - 1]; + TimerBarRow& row = mHoverBarIndex == 0 ? mAverageTimerRow : mTimerBarRows[mScrollIndex + mHoverBarIndex - 1]; TimerBar* hover_bar = NULL; LLUnit<F32, LLUnits::Seconds> mouse_time_offset = ((F32)(x - mBarRect.mLeft) / (F32)mBarRect.getWidth()) * mTotalTimeDisplay; - for (std::vector<TimerBar>::iterator it = row.mBars.begin(), end_it = row.mBars.end(); - it != end_it; - ++it) + for (int bar_index = 0, end_index = LLInstanceTracker<LLTrace::TimeBlock>::instanceCount(); + bar_index < end_index; + ++bar_index) { - if (it->mSelfStart > mouse_time_offset) + TimerBar& bar = row.mBars[bar_index]; + if (bar.mSelfStart > mouse_time_offset) { break; } - hover_bar = &(*it); + if (bar.mSelfEnd > mouse_time_offset) + { + hover_bar = &bar; + if (bar.mTimeBlock->getCollapsed()) + { + // stop on first collapsed timeblock, since we can't select any children + break; + } + } } if (hover_bar) { mHoverID = hover_bar->mTimeBlock; - mHoverTimer = mHoverID; if (mHoverTimer != mHoverID) { // could be that existing tooltip is for a parent and is thus @@ -300,7 +293,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) mHoverTimer = mHoverID; mToolTipRect.set(mBarRect.mLeft + (hover_bar->mSelfStart / mTotalTimeDisplay) * mBarRect.getWidth(), row.mTop, - mBarRect.mLeft + (hover_bar->mSelfStart / mTotalTimeDisplay) * mBarRect.getWidth(), + mBarRect.mLeft + (hover_bar->mSelfEnd / mTotalTimeDisplay) * mBarRect.getWidth(), row.mBottom); } } @@ -324,7 +317,7 @@ static std::string get_tooltip(TimeBlock& timer, S32 history_index, PeriodicReco if (history_index == 0) { // by default, show average number of call - tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit<F64, LLUnits::Milliseconds>(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 { @@ -397,22 +390,34 @@ void LLFastTimerView::draw() 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)); - - // update rectangle that includes timer bars - const S32 LEGEND_WIDTH = 220; + drawHelp(getRect().getHeight() - MARGIN); + drawLegend(); - mBarRect.mLeft = MARGIN + LEGEND_WIDTH + 8; - mBarRect.mTop = y; - mBarRect.mRight = getRect().getWidth() - MARGIN; - mBarRect.mBottom = MARGIN + LINE_GRAPH_HEIGHT; + //mBarRect.mLeft = MARGIN + LEGEND_WIDTH + 8; + //mBarRect.mTop = y; + //mBarRect.mRight = getRect().getWidth() - MARGIN; + //mBarRect.mBottom = MARGIN + LINE_GRAPH_HEIGHT; drawBars(); drawLineGraph(); @@ -433,7 +438,8 @@ void LLFastTimerView::onOpen(const LLSD& key) it != end_it; ++it) { - it->mBars.clear(); + delete []it->mBars; + it->mBars = NULL; } } @@ -993,7 +999,7 @@ void LLFastTimerView::printLineStats() LLUnit<F32, LLUnits::Seconds> ticks; if (mStatsIndex == 0) { - ticks = mRecording.getPeriodMean(*idp); + ticks = mRecording.getPeriodMean(*idp, RUNNING_AVERAGE_WIDTH); } else { @@ -1019,8 +1025,6 @@ void LLFastTimerView::drawLineGraph() { LLFastTimer _(FTM_DRAW_LINE_GRAPH); //draw line graph history - S32 x = mBarRect.mLeft; - S32 y = LINE_GRAPH_HEIGHT; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLLocalClipRect clip(mGraphRect); @@ -1029,21 +1033,6 @@ void LLFastTimerView::drawLineGraph() static U32 max_calls = 0; static F32 alpha_interp = 0.f; - //display y-axis range - std::string axis_label; - if (mDisplayCalls) - axis_label = llformat("%d calls", (int)max_calls); - else if (mDisplayHz) - axis_label = llformat("%d Hz", (int)(1.f / max_time.value())); - else - axis_label = llformat("%4.2f ms", LLUnit<F32, LLUnits::Milliseconds>(max_time).value()); - - x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(axis_label)-5; - y = mGraphRect.mTop - LLFontGL::getFontMonospace()->getLineHeight(); - - LLFontGL::getFontMonospace()->renderUTF8(axis_label, 0, x, y, LLColor4::white, - LLFontGL::LEFT, LLFontGL::TOP); - //highlight visible range { S32 first_frame = mRecording.getNumRecordedPeriods() - mScrollIndex; @@ -1059,7 +1048,7 @@ void LLFastTimerView::drawLineGraph() if (mHoverBarIndex > 0) { - S32 bar_frame = first_frame - mHoverBarIndex - 1; + S32 bar_frame = first_frame - (mScrollIndex + mHoverBarIndex) - 1; F32 bar = (F32) mGraphRect.mLeft + frame_delta*bar_frame; gGL.color4f(0.5f,0.5f,0.5f,1); @@ -1090,6 +1079,7 @@ void LLFastTimerView::drawLineGraph() const F32 * col = sTimerColors[idp->getIndex()].mV;// ft_display_table[idx].color->mV; F32 alpha = 1.f; + bool is_hover_timer = true; if (mHoverID != NULL && mHoverID != idp) @@ -1097,11 +1087,15 @@ void LLFastTimerView::drawLineGraph() if (idp->getParent() != mHoverID) { alpha = alpha_interp; + is_hover_timer = false; } } gGL.color4f(col[0], col[1], col[2], alpha); gGL.begin(LLRender::TRIANGLE_STRIP); + F32 call_scale_factor = (F32)mGraphRect.getHeight() / (F32)max_calls; + F32 time_scale_factor = (F32)mGraphRect.getHeight() / max_time.value(); + F32 hz_scale_factor = (F32) mGraphRect.getHeight() / (1.f / max_time.value()); for (U32 j = mRecording.getNumRecordedPeriods(); j > 0; j--) @@ -1110,16 +1104,26 @@ void LLFastTimerView::drawLineGraph() LLUnit<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.getNumRecordedPeriods()-1); - F32 y = mDisplayHz - ? mGraphRect.mBottom + (1.f / time.value()) * ((F32) mGraphRect.getHeight() / (1.f / max_time.value())) - : mGraphRect.mBottom + time / max_time * (F32)mGraphRect.getHeight(); + F32 y; + switch(mDisplayType) + { + case TIME: + y = mGraphRect.mBottom + time.value() * time_scale_factor; + break; + case CALLS: + y = mGraphRect.mBottom + (F32)calls * call_scale_factor; + break; + case HZ: + y = mGraphRect.mBottom + (1.f / time.value()) * hz_scale_factor; + break; + } gGL.vertex2f(x,y); gGL.vertex2f(x,mGraphRect.mBottom); } @@ -1140,7 +1144,7 @@ void LLFastTimerView::drawLineGraph() //interpolate towards new maximum max_time = lerp(max_time.value(), cur_max.value(), LLSmoothInterpolation::getInterpolant(0.1f)); - if (max_time - cur_max <= 1 || cur_max - max_time <= 1) + if (llabs((max_time - cur_max).value()) <= 1) { max_time = llmax(LLUnit<F32, LLUnits::Microseconds>(1), LLUnit<F32, LLUnits::Microseconds>(cur_max)); } @@ -1159,8 +1163,8 @@ void LLFastTimerView::drawLineGraph() if (mHoverID != NULL) { - x = (mGraphRect.mRight + mGraphRect.mLeft)/2; - y = mGraphRect.mBottom + 8; + S32 x = (mGraphRect.mRight + mGraphRect.mLeft)/2; + S32 y = mGraphRect.mBottom + 8; LLFontGL::getFontMonospace()->renderUTF8( mHoverID->getName(), @@ -1168,18 +1172,40 @@ void LLFastTimerView::drawLineGraph() x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM); - } + } + + //display y-axis range + std::string axis_label; + switch(mDisplayType) + { + case TIME: + axis_label = llformat("%4.2f ms", LLUnit<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; @@ -1214,18 +1240,22 @@ void LLFastTimerView::drawLegend( S32 y ) } else { - ms = LLUnit<F64, LLUnits::Seconds>(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; @@ -1300,36 +1330,16 @@ void LLFastTimerView::generateUniqueColors() } } -S32 LLFastTimerView::drawHelp( S32 y ) +void LLFastTimerView::drawHelp( S32 y ) { // Draw some help const S32 texth = (S32)LLFontGL::getFontMonospace()->getLineHeight(); - char modedesc[][32] = { - "2 x Average ", - "Max ", - "Recent Max ", - "100 ms " - }; - char centerdesc[][32] = { - "Left ", - "Centered ", - "Ordered " - }; - - std::string text; - text = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, MARGIN, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - y -= (texth + 2); - text = llformat("Justification = %s [CTRL-Click to toggle]",centerdesc[mDisplayCenter]); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, MARGIN, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); y -= (texth + 2); - LLFontGL::getFontMonospace()->renderUTF8(std::string("[Right-Click log selected] [ALT-Click toggle counts] [ALT-SHIFT-Click sub hidden]"), + LLFontGL::getFontMonospace()->renderUTF8(std::string("[Right-Click log selected] [ALT-Click toggle counts]"), 0, MARGIN, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - y -= (texth + 2); - return y; } void LLFastTimerView::drawTicks() @@ -1392,7 +1402,7 @@ void LLFastTimerView::drawBorders( S32 y, const S32 x_start, S32 bar_height, S32 by = LINE_GRAPH_HEIGHT-dy; //line graph - mGraphRect = LLRect(x_start-5, by, getRect().getWidth()-5, 5); + //mGraphRect = LLRect(x_start-5, by, getRect().getWidth()-5, 5); gl_rect_2d(mGraphRect, FALSE); } @@ -1403,7 +1413,7 @@ void LLFastTimerView::updateTotalTime() switch(mDisplayMode) { case 0: - mTotalTimeDisplay = mRecording.getPeriodMean(FTM_FRAME, 100)*2; + mTotalTimeDisplay = mRecording.getPeriodMean(FTM_FRAME, RUNNING_AVERAGE_WIDTH)*2; break; case 1: mTotalTimeDisplay = mRecording.getPeriodMax(FTM_FRAME); @@ -1447,18 +1457,27 @@ void LLFastTimerView::drawBars() const S32 histmax = (S32)mRecording.getNumRecordedPeriods(); // update widths - updateTimerBarWidths(&FTM_FRAME, mAverageTimerRow, -1); - updateTimerBarOffsets(&FTM_FRAME, mAverageTimerRow); - - for (S32 history_index = 1; history_index <= histmax; history_index++) + if (!mPauseHistory) { - llassert(history_index <= mTimerBarRows.size()); - TimerBarRow& row = mTimerBarRows[history_index - 1]; - if (row.mBars.empty()) + U32 bar_index = 0; + if (!mAverageTimerRow.mBars) { - row.mBars.reserve(LLInstanceTracker<LLTrace::TimeBlock>::instanceCount()); - updateTimerBarWidths(&FTM_FRAME, row, history_index); - updateTimerBarOffsets(&FTM_FRAME, row); + 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); + } } } @@ -1492,32 +1511,28 @@ void LLFastTimerView::drawBars() static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_WIDTHS("Update timer bar widths"); -LLUnit<F32, LLUnits::Seconds> LLFastTimerView::updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, 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); const LLUnit<F32, LLUnits::Seconds> self_time = history_index == -1 - ? mRecording.getPeriodMean(time_block->selfTime()) + ? mRecording.getPeriodMean(time_block->selfTime(), RUNNING_AVERAGE_WIDTH) : mRecording.getPrevRecording(history_index).getSum(time_block->selfTime()); LLUnit<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 - std::vector<TimerBar>& bars = row.mBars; - S32 bar_index = bars.size(); - bars.push_back(TimerBar()); + TimerBar& timer_bar = row.mBars[bar_index]; + bar_index++; - const bool children_visible = visible && !time_block->getCollapsed(); for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); it != end_it; ++it) { - full_time += updateTimerBarWidths(*it, row, history_index, children_visible); + full_time += updateTimerBarWidths(*it, row, history_index, bar_index); } - TimerBar& timer_bar = bars[bar_index]; timer_bar.mTotalTime = full_time; timer_bar.mSelfTime = self_time; timer_bar.mTimeBlock = time_block; - timer_bar.mVisible = visible; return full_time; } @@ -1528,21 +1543,16 @@ S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, Timer { LLFastTimer _(FTM_UPDATE_TIMER_BAR_FRACTIONS); - std::vector<TimerBar>& bars = row.mBars; - llassert(timer_bar_index < bars.size()); - TimerBar& timer_bar = bars[timer_bar_index]; - const LLUnit<F32, LLUnits::Seconds> child_time_width = timer_bar.mTotalTime - timer_bar.mSelfTime; - timer_bar.mChildrenStart = timer_bar.mSelfStart; + TimerBar& timer_bar = row.mBars[timer_bar_index]; + const LLUnit<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 (mDisplayCenter == ALIGN_CENTER) + if (timer_bar_index == 0) { - timer_bar.mChildrenStart += timer_bar.mSelfTime / 2; + timer_bar.mSelfStart = 0.f; + timer_bar.mSelfEnd = bar_time; } - else if (mDisplayCenter == ALIGN_RIGHT) - { - timer_bar.mChildrenStart += timer_bar.mSelfTime; - } - timer_bar.mChildrenEnd = timer_bar.mChildrenStart + timer_bar.mTotalTime - timer_bar.mSelfTime; //now loop through children and figure out portion of bar image covered by each bar, now that we know the //sum of all children @@ -1556,8 +1566,7 @@ S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, Timer { timer_bar_index++; - llassert(timer_bar_index < bars.size()); - TimerBar& child_timer_bar = bars[timer_bar_index]; + TimerBar& child_timer_bar = row.mBars[timer_bar_index]; TimeBlock* child_time_block = *it; if (last_child_timer_bar) @@ -1574,15 +1583,15 @@ S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, Timer } child_timer_bar.mStartFraction = bar_fraction_start; - child_timer_bar.mEndFraction = child_time_width > 0 - ? bar_fraction_start + child_timer_bar.mTotalTime / child_time_width + child_timer_bar.mEndFraction = bar_time > 0 + ? bar_fraction_start + child_timer_bar.mTotalTime / bar_time : 1.f; - child_timer_bar.mSelfStart = timer_bar.mChildrenStart
- + child_timer_bar.mStartFraction
- * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart);
- child_timer_bar.mSelfEnd = timer_bar.mChildrenStart
- + child_timer_bar.mEndFraction
- * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart);
+ child_timer_bar.mSelfStart = timer_bar.mChildrenStart + + child_timer_bar.mStartFraction + * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart); + child_timer_bar.mSelfEnd = timer_bar.mChildrenStart + + child_timer_bar.mEndFraction + * (timer_bar.mChildrenEnd - timer_bar.mChildrenStart); timer_bar_index = updateTimerBarOffsets(child_time_block, row, timer_bar_index); @@ -1591,16 +1600,15 @@ S32 LLFastTimerView::updateTimerBarOffsets(LLTrace::TimeBlock* time_block, Timer return timer_bar_index; } -S32 LLFastTimerView::drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, S32 bar_index) +S32 LLFastTimerView::drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered, bool visible, S32 bar_index) { - llassert(bar_index < row.mBars.size()); TimerBar& timer_bar = row.mBars[bar_index]; LLTrace::TimeBlock* time_block = timer_bar.mTimeBlock; hovered |= mHoverID == time_block; // animate scale of bar when hovering over that particular timer - if ((F32)bar_rect.getWidth() * (timer_bar.mEndFraction - timer_bar.mStartFraction) > 2.f) + if (visible && (F32)bar_rect.getWidth() * (timer_bar.mEndFraction - timer_bar.mStartFraction) > 2.f) { LLRect render_rect(bar_rect); S32 scale_offset = 0; @@ -1637,15 +1645,17 @@ S32 LLFastTimerView::drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, children_rect.mBottom = bar_rect.mBottom; } + bool children_visible = visible && !time_block->getCollapsed(); + bar_index++; - const U32 num_bars = row.mBars.size(); + const U32 num_bars = LLInstanceTracker<LLTrace::TimeBlock>::instanceCount(); if (bar_index < num_bars && row.mBars[bar_index].mFirstChild) { bool is_last = false; do { is_last = row.mBars[bar_index].mLastChild; - bar_index = drawBar(children_rect, row, image_width, image_height, hovered, bar_index); + bar_index = drawBar(children_rect, row, image_width, image_height, hovered, children_visible, bar_index); } while(!is_last && bar_index < num_bars); } diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index d9ae6348da..d931f25a7e 100755 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -68,8 +68,8 @@ private: virtual void onClickCloseBtn(); void drawTicks(); void drawLineGraph(); - void drawLegend(S32 y); - S32 drawHelp(S32 y); + void drawLegend(); + void drawHelp(S32 y); void drawBorders( S32 y, const S32 x_start, S32 barh, S32 dy); void drawBars(); @@ -82,7 +82,6 @@ private: TimerBar() : mTotalTime(0), mSelfTime(0), - mVisible(true), mStartFraction(0.f), mEndFraction(1.f), mFirstChild(false), @@ -104,29 +103,26 @@ private: struct TimerBarRow { - S32 mBottom, - mTop; - std::vector<TimerBar> mBars; + S32 mBottom, + mTop; + TimerBar* mBars; }; - LLUnit<F32, LLUnits::Seconds> updateTimerBarWidths(LLTrace::TimeBlock* time_block, TimerBarRow& row, S32 history_index, bool visible = true); + 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, S32 bar_index = 0); + S32 drawBar(LLRect bar_rect, TimerBarRow& row, S32 image_width, S32 image_height, bool hovered = false, bool visible = true, S32 bar_index = 0); void setPauseState(bool pause_state); std::deque<TimerBarRow> mTimerBarRows; TimerBarRow mAverageTimerRow; - enum ChildAlignment + enum EDisplayType { - ALIGN_LEFT, - ALIGN_CENTER, - ALIGN_RIGHT, - ALIGN_COUNT - } mDisplayCenter; - bool mDisplayCalls, - mDisplayHz, - mPauseHistory; + TIME, + CALLS, + HZ + } mDisplayType; + bool mPauseHistory; LLUnit<F64, LLUnits::Seconds> mAllTimeMax, mTotalTimeDisplay; S32 mScrollIndex, @@ -137,7 +133,8 @@ private: LLTrace::TimeBlock* mHoverTimer; LLRect mToolTipRect, mGraphRect, - mBarRect; + mBarRect, + mLegendRect; LLFrameTimer mHighlightTimer; LLTrace::PeriodicRecording mRecording; }; diff --git a/indra/newview/skins/default/xui/en/floater_fast_timers.xml b/indra/newview/skins/default/xui/en/floater_fast_timers.xml index 77adb5524e..671f116df3 100755 --- a/indra/newview/skins/default/xui/en/floater_fast_timers.xml +++ b/indra/newview/skins/default/xui/en/floater_fast_timers.xml @@ -16,6 +16,27 @@ width="700"> <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> |