diff options
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> | 
