improved fast timers display

can move and resize
better visualization of timer history
can click drag to browse history
increased frame history to 300
master
Richard Nelson 2011-09-14 10:50:32 -07:00
parent aa75136e1a
commit 8b7c07651c
8 changed files with 131 additions and 93 deletions

View File

@ -303,14 +303,15 @@ LLFastTimer::NamedTimer::~NamedTimer()
std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
{
F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond();
if (history_idx < 0)
{
// by default, show average number of calls
return llformat("%s (%d calls)", getName().c_str(), (S32)getCallAverage());
// by default, show average number of call
return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getCountAverage() * ms_multiplier), (S32)getCallAverage());
}
else
{
return llformat("%s (%d calls)", getName().c_str(), (S32)getHistoricalCalls(history_idx));
return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx));
}
}
@ -693,17 +694,7 @@ void LLFastTimer::nextFrame()
llinfos << "Slow frame, fast timers inaccurate" << llendl;
}
if (sPauseHistory)
{
sResetHistory = true;
}
else if (sResetHistory)
{
sLastFrameIndex = 0;
sCurFrameIndex = 0;
sResetHistory = false;
}
else // not paused
if (!sPauseHistory)
{
NamedTimer::processTimes();
sLastFrameIndex = sCurFrameIndex++;

View File

@ -66,7 +66,7 @@ public:
public:
~NamedTimer();
enum { HISTORY_NUM = 60 };
enum { HISTORY_NUM = 300 };
const std::string& getName() const { return mName; }
NamedTimer* getParent() const { return mParent; }

View File

@ -41,6 +41,7 @@
#include "llmemoryview.h"
#include "llsceneview.h"
#include "llviewertexture.h"
#include "llfloaterreg.h"
//
// Globals
@ -79,12 +80,7 @@ void LLDebugView::init()
r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f),
(S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f));
mFastTimerView = new LLFastTimerView(r);
mFastTimerView->setFollowsTop();
mFastTimerView->setFollowsLeft();
mFastTimerView->setVisible(FALSE); // start invisible
addChild(mFastTimerView);
mFastTimerView->setRect(rect);
mFastTimerView = dynamic_cast<LLFastTimerView*>(LLFloaterReg::getInstance("fast_timers"));
gSceneView = new LLSceneView(r);
gSceneView->setFollowsTop();

View File

@ -80,12 +80,10 @@ static timer_tree_iterator_t end_timer_tree()
return timer_tree_iterator_t();
}
LLFastTimerView::LLFastTimerView(const LLRect& rect)
: LLFloater(LLSD()),
LLFastTimerView::LLFastTimerView(const LLSD& key)
: LLFloater(key),
mHoverTimer(NULL)
{
setRect(rect);
setVisible(FALSE);
mDisplayMode = 0;
mAvgCountTotal = 0;
mMaxCountTotal = 0;
@ -98,10 +96,30 @@ LLFastTimerView::LLFastTimerView(const LLRect& rect)
FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount();
mPrintStats = -1;
mAverageCyclesPerTimer = 0;
setCanMinimize(false);
setCanClose(true);
}
void LLFastTimerView::onPause()
{
LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
// reset scroll to bottom when unpausing
if (!LLFastTimer::sPauseHistory)
{
mScrollIndex = 0;
getChild<LLButton>("pause_btn")->setLabel(getString("pause"));
}
else
{
getChild<LLButton>("pause_btn")->setLabel(getString("run"));
}
}
BOOL LLFastTimerView::postBuild()
{
LLButton& pause_btn = getChildRef<LLButton>("pause_btn");
pause_btn.setCommitCallback(boost::bind(&LLFastTimerView::onPause, this));
return TRUE;
}
BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
@ -116,14 +134,16 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
mHoverTimer->getParent()->setCollapsed(true);
}
return TRUE;
}
else if (mBarRect.pointInRect(x, y))
{
S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());
bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY);
mPrintStats = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - bar_idx;
return TRUE;
}
return FALSE;
return LLFloater::handleRightMouseDown(x, y, mask);
}
LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y)
@ -151,18 +171,6 @@ BOOL LLFastTimerView::handleDoubleClick(S32 x, S32 y, MASK mask)
BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
{
{
S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft;
S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom;
if(mButtons[BUTTON_CLOSE]->getVisible()
&& mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y) )
{
return LLFloater::handleMouseDown(x, y, mask);;
}
}
if (x < mBarRect.mLeft)
{
LLFastTimer::NamedTimer* idp = getLegendID(y);
@ -196,36 +204,42 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
{
mDisplayCenter = (ChildAlignment)((mDisplayCenter + 1) % ALIGN_COUNT);
}
else
else if (mGraphRect.pointInRect(x, y))
{
// pause/unpause
LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
// reset scroll to bottom when unpausing
if (!LLFastTimer::sPauseHistory)
{
mScrollIndex = 0;
}
gFocusMgr.setMouseCapture(this);
return TRUE;
}
// SJB: Don't pass mouse clicks through the display
return TRUE;
//else
//{
// // pause/unpause
// LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
// // reset scroll to bottom when unpausing
// if (!LLFastTimer::sPauseHistory)
// {
// mScrollIndex = 0;
// }
//}
return LLFloater::handleMouseDown(x, y, mask);
}
BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask)
{
if (hasMouseCapture())
{
S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft;
S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom;
if(mButtons[BUTTON_CLOSE]->getVisible()
&& mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y) )
{
return LLFloater::handleMouseUp(x, y, mask);;
}
gFocusMgr.setMouseCapture(NULL);
}
return FALSE;
return LLFloater::handleMouseUp(x, y, mask);;
}
BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
{
if (hasMouseCapture())
{
F32 lerp = llclamp(1.f - (F32) (x - mGraphRect.mLeft) / (F32) mGraphRect.getWidth(), 0.f, 1.f);
mScrollIndex = llround( lerp * (F32)(LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY));
mScrollIndex = llclamp( mScrollIndex, 0, LLFastTimer::getLastFrameIndex());
return TRUE;
}
mHoverTimer = NULL;
mHoverID = NULL;
@ -282,7 +296,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
}
}
return FALSE;
return LLFloater::handleHover(x, y, mask);
}
@ -318,15 +332,15 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask)
}
}
}
return FALSE;
return LLFloater::handleToolTip(x, y, mask);
}
BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
LLFastTimer::sPauseHistory = TRUE;
mScrollIndex = llclamp(mScrollIndex - clicks,
0,
mScrollIndex = llclamp( mScrollIndex + clicks,
0,
llmin(LLFastTimer::getLastFrameIndex(), (S32)LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY));
return TRUE;
}
@ -345,8 +359,8 @@ void LLFastTimerView::draw()
F64 iclock_freq = 1000.0 / clock_freq;
S32 margin = 10;
S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);
S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f);
S32 height = getRect().getHeight();
S32 width = getRect().getWidth();
LLRect new_rect;
new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height);
@ -630,7 +644,6 @@ void LLFastTimerView::draw()
LLFontGL::LEFT, LLFontGL::TOP);
}
LLRect graph_rect;
// Draw borders
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@ -663,9 +676,9 @@ void LLFastTimerView::draw()
by = LINE_GRAPH_HEIGHT-barh-dy-7;
//line graph
graph_rect = LLRect(xleft-5, by, getRect().getWidth()-5, 5);
mGraphRect = LLRect(xleft-5, by, getRect().getWidth()-5, 5);
gl_rect_2d(graph_rect, FALSE);
gl_rect_2d(mGraphRect, FALSE);
}
mBarStart.clear();
@ -813,7 +826,7 @@ void LLFastTimerView::draw()
//draw line graph history
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLLocalClipRect clip(graph_rect);
LLLocalClipRect clip(mGraphRect);
//normalize based on last frame's maximum
static U64 last_max = 0;
@ -830,8 +843,8 @@ void LLFastTimerView::draw()
else
tdesc = llformat("%4.2f ms", ms);
x = graph_rect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5;
y = graph_rect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight());
x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5;
y = mGraphRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight());
LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white,
LLFontGL::LEFT, LLFontGL::TOP);
@ -841,24 +854,24 @@ void LLFastTimerView::draw()
S32 first_frame = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex;
S32 last_frame = first_frame - MAX_VISIBLE_HISTORY;
F32 frame_delta = ((F32) (graph_rect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1);
F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1);
F32 right = (F32) graph_rect.mLeft + frame_delta*first_frame;
F32 left = (F32) graph_rect.mLeft + frame_delta*last_frame;
F32 right = (F32) mGraphRect.mLeft + frame_delta*first_frame;
F32 left = (F32) mGraphRect.mLeft + frame_delta*last_frame;
gGL.color4f(0.5f,0.5f,0.5f,0.3f);
gl_rect_2d((S32) left, graph_rect.mTop, (S32) right, graph_rect.mBottom);
gl_rect_2d((S32) left, mGraphRect.mTop, (S32) right, mGraphRect.mBottom);
if (mHoverBarIndex >= 0)
{
S32 bar_frame = first_frame - mHoverBarIndex;
F32 bar = (F32) graph_rect.mLeft + frame_delta*bar_frame;
F32 bar = (F32) mGraphRect.mLeft + frame_delta*bar_frame;
gGL.color4f(0.5f,0.5f,0.5f,1);
gGL.begin(LLRender::LINES);
gGL.vertex2i((S32)bar, graph_rect.mBottom);
gGL.vertex2i((S32)bar, graph_rect.mTop);
gGL.vertex2i((S32)bar, mGraphRect.mBottom);
gGL.vertex2i((S32)bar, mGraphRect.mTop);
gGL.end();
}
}
@ -883,7 +896,7 @@ void LLFastTimerView::draw()
if (mHoverID != NULL &&
idp != mHoverID)
{ //fade out non-hihglighted timers
{ //fade out non-highlighted timers
if (idp->getParent() != mHoverID)
{
alpha = alpha_interp;
@ -891,8 +904,10 @@ void LLFastTimerView::draw()
}
gGL.color4f(col[0], col[1], col[2], alpha);
gGL.begin(LLRender::LINE_STRIP);
for (U32 j = 0; j < LLFastTimer::NamedTimer::HISTORY_NUM; j++)
gGL.begin(LLRender::TRIANGLE_STRIP);
for (U32 j = llmax(0, LLFastTimer::NamedTimer::HISTORY_NUM - LLFastTimer::getLastFrameIndex());
j < LLFastTimer::NamedTimer::HISTORY_NUM;
j++)
{
U64 ticks = idp->getHistoricalCount(j);
@ -912,9 +927,10 @@ void LLFastTimerView::draw()
//normalize to highlighted timer
cur_max = llmax(cur_max, ticks);
}
F32 x = graph_rect.mLeft + ((F32) (graph_rect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1)*j;
F32 y = graph_rect.mBottom + (F32) graph_rect.getHeight()/max_ticks*ticks;
F32 x = mGraphRect.mLeft + ((F32) (mGraphRect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1)*j;
F32 y = mGraphRect.mBottom + (F32) mGraphRect.getHeight()/max_ticks*ticks;
gGL.vertex2f(x,y);
gGL.vertex2f(x,mGraphRect.mBottom);
}
gGL.end();
@ -932,18 +948,20 @@ void LLFastTimerView::draw()
}
//interpolate towards new maximum
F32 dt = gFrameIntervalSeconds*3.f;
last_max = (U64) ((F32) last_max + ((F32) cur_max- (F32) last_max) * dt);
last_max = (U64) lerp((F32)last_max, (F32) cur_max, LLCriticalDamp::getInterpolant(0.1f));
if (last_max - cur_max <= 1 || cur_max - last_max <= 1)
{
last_max = cur_max;
}
F32 alpha_target = last_max > cur_max ?
llmin((F32) last_max/ (F32) cur_max - 1.f,1.f) :
llmin((F32) cur_max/ (F32) last_max - 1.f,1.f);
alpha_interp = alpha_interp + (alpha_target-alpha_interp) * dt;
alpha_interp = lerp(alpha_interp, alpha_target, LLCriticalDamp::getInterpolant(0.1f));
if (mHoverID != NULL)
{
x = (graph_rect.mRight + graph_rect.mLeft)/2;
y = graph_rect.mBottom + 8;
x = (mGraphRect.mRight + mGraphRect.mLeft)/2;
y = mGraphRect.mBottom + 8;
LLFontGL::getFontMonospace()->renderUTF8(
mHoverID->getName(),

View File

@ -33,8 +33,9 @@
class LLFastTimerView : public LLFloater
{
public:
LLFastTimerView(const LLRect& rect);
LLFastTimerView(const LLSD&);
BOOL postBuild();
static BOOL sAnalyzePerformance;
static void outputAllMetrics();
@ -44,6 +45,7 @@ private:
static void doAnalysisDefault(std::string baseline, std::string target, std::string output) ;
static LLSD analyzePerformanceLogDefault(std::istream& is) ;
static void exportCharts(const std::string& base, const std::string& target);
void onPause();
public:
@ -89,6 +91,7 @@ private:
LLFrameTimer mHighlightTimer;
S32 mPrintStats;
S32 mAverageCyclesPerTimer;
LLRect mGraphRect;
};
#endif

View File

@ -33,6 +33,7 @@
#include "llcompilequeue.h"
#include "llcallfloater.h"
#include "llfasttimerview.h"
#include "llfloaterabout.h"
#include "llfloateranimpreview.h"
#include "llfloaterauction.h"
@ -159,6 +160,7 @@ void LLViewerFloaterReg::registerFloaters()
// *NOTE: Please keep these alphabetized for easier merges
LLFloaterAboutUtil::registerFloater();
LLFloaterReg::add("fast_timers", "floater_fast_timers.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFastTimerView>);
LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>);
LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>);
LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarPicker>);

View File

@ -523,7 +523,7 @@ class LLAdvancedToggleConsole : public view_listener_t
}
else if ("fast timers" == console_type)
{
toggle_visibility( (void*)gDebugView->mFastTimerView );
LLFloaterReg::toggleInstance("fast_timers");
}
else if ("scene view" == console_type)
{
@ -563,7 +563,7 @@ class LLAdvancedCheckConsole : public view_listener_t
}
else if ("fast timers" == console_type)
{
new_value = get_visibility( (void*)gDebugView->mFastTimerView );
new_value = LLFloaterReg::instanceVisible("fast_timers");
}
else if ("scene view" == console_type)
{

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
legacy_header_height="18"
can_minimize="false"
can_tear_off="false"
can_resize="true"
can_drag_on_left="false"
can_close="true"
height="500"
layout="topleft"
name="fast_timers"
save_rect="true"
save_visibility="false"
single_instance="true"
min_width="400"
width="700">
<string name="pause" >Pause</string>
<string name="run">Run</string>
<button follows="top|right"
name="pause_btn"
left="-200"
top="5"
width="180"
height="40"
pad_bottom="-5"
label="Pause"
font="SansSerifHuge"/>
</floater>