diff options
Diffstat (limited to 'indra/newview/llfasttimerview.cpp')
-rw-r--r-- | indra/newview/llfasttimerview.cpp | 1138 |
1 files changed, 570 insertions, 568 deletions
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index c9037d0fbb..8ceb41c27a 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -41,295 +41,117 @@ #include "llrender.h" #include "llmath.h" #include "llfontgl.h" +#include "llsdserialize.h" #include "llappviewer.h" -#include "llviewerimagelist.h" +#include "llviewertexturelist.h" #include "llui.h" #include "llviewercontrol.h" #include "llstat.h" #include "llfasttimer.h" - +#include "lltreeiterators.h" +#include "llmetricperformancetester.h" ////////////////////////////////////////////////////////////////////////////// static const S32 MAX_VISIBLE_HISTORY = 10; static const S32 LINE_GRAPH_HEIGHT = 240; -struct ft_display_info { - int timer; - const char *desc; - const LLColor4 *color; - S32 disabled; // initialized to 0 - int level; // calculated based on desc - int parent; // calculated -}; - -static const LLColor4 red0(0.5f, 0.0f, 0.0f, 1.0f); -static const LLColor4 green0(0.0f, 0.5f, 0.0f, 1.0f); -static const LLColor4 blue0(0.0f, 0.0f, 0.5f, 1.0f); -static const LLColor4 blue7(0.0f, 0.0f, 0.5f, 1.0f); - -static const LLColor4 green7(0.6f, 1.0f, 0.4f, 1.0f); -static const LLColor4 green8(0.4f, 1.0f, 0.6f, 1.0f); -static const LLColor4 green9(0.6f, 1.0f, 0.6f, 1.0f); - -// green(6), blue, yellow, orange, pink(2), cyan -// red (5) magenta (4) -static struct ft_display_info ft_display_table[] = -{ - { LLFastTimer::FTM_FRAME, "Frame", &LLColor4::white, 0 }, - { LLFastTimer::FTM_MESSAGES, " System Messages", &LLColor4::grey1, 1 }, - { LLFastTimer::FTM_MOUSEHANDLER, " Mouse", &LLColor4::grey1, 0 }, - { LLFastTimer::FTM_KEYHANDLER, " Keyboard", &LLColor4::grey1, 0 }, - { LLFastTimer::FTM_SLEEP, " Sleep", &LLColor4::grey2, 0 }, - { LLFastTimer::FTM_IDLE, " Idle", &blue0, 0 }, - { LLFastTimer::FTM_PUMP, " Pump", &LLColor4::magenta2, 1 }, - { LLFastTimer::FTM_CURL, " Curl", &LLColor4::magenta3, 0 }, - { LLFastTimer::FTM_INVENTORY, " Inventory Update", &LLColor4::purple6, 1 }, - { LLFastTimer::FTM_AUTO_SELECT, " Open and Select", &LLColor4::red, 0 }, - { LLFastTimer::FTM_FILTER, " Filter", &LLColor4::red2, 0 }, - { LLFastTimer::FTM_ARRANGE, " Arrange", &LLColor4::red3, 0 }, - { LLFastTimer::FTM_REFRESH, " Refresh", &LLColor4::red4, 0 }, - { LLFastTimer::FTM_SORT, " Sort", &LLColor4::red5, 0 }, - { LLFastTimer::FTM_RESET_DRAWORDER, " ResetDrawOrder", &LLColor4::pink1, 0 }, - { LLFastTimer::FTM_WORLD_UPDATE, " World Update", &LLColor4::blue1, 1 }, - { LLFastTimer::FTM_UPDATE_MOVE, " Move Objects", &LLColor4::pink2, 0 }, - { LLFastTimer::FTM_OCTREE_BALANCE, " Octree Balance", &LLColor4::red3, 0 }, - { LLFastTimer::FTM_SIMULATE_PARTICLES, " Particle Sim", &LLColor4::blue4, 0 }, - { LLFastTimer::FTM_OBJECTLIST_UPDATE, " Object Update", &LLColor4::purple1, 1 }, - { LLFastTimer::FTM_AVATAR_UPDATE, " Avatars", &LLColor4::purple2, 0 }, - { LLFastTimer::FTM_JOINT_UPDATE, " Joints", &LLColor4::purple3, 0 }, - { LLFastTimer::FTM_ATTACHMENT_UPDATE, " Attachments", &LLColor4::purple4, 0 }, - { LLFastTimer::FTM_UPDATE_ANIMATION, " Animation", &LLColor4::purple5, 0 }, - { LLFastTimer::FTM_FLEXIBLE_UPDATE, " Flex Update", &LLColor4::pink2, 0 }, - { LLFastTimer::FTM_LOD_UPDATE, " LOD Update", &LLColor4::magenta1, 0 }, - { LLFastTimer::FTM_REGION_UPDATE, " Region Update", &LLColor4::cyan2, 0 }, - { LLFastTimer::FTM_NETWORK, " Network", &LLColor4::orange1, 1 }, - { LLFastTimer::FTM_IDLE_NETWORK, " Decode Msgs", &LLColor4::orange2, 0 }, - { LLFastTimer::FTM_PROCESS_MESSAGES, " Process Msgs", &LLColor4::orange3, 0 }, - { LLFastTimer::FTM_PROCESS_OBJECTS, " Object Updates",&LLColor4::orange4, 0 }, - { LLFastTimer::FTM_CREATE_OBJECT, " Create Obj", &LLColor4::orange5, 0 }, -// { LLFastTimer::FTM_LOAD_AVATAR, " Load Avatar", &LLColor4::pink2, 0 }, - { LLFastTimer::FTM_PROCESS_IMAGES, " Image Updates",&LLColor4::orange6, 0 }, - { LLFastTimer::FTM_PIPELINE, " Pipeline", &LLColor4::magenta4, 0 }, - { LLFastTimer::FTM_CLEANUP, " Cleanup", &LLColor4::cyan3, 0 }, - { LLFastTimer::FTM_AUDIO_UPDATE, " Audio Update", &LLColor4::yellow3, 0 }, - { LLFastTimer::FTM_VFILE_WAIT, " VFile Wait", &LLColor4::cyan6, 0 }, -// { LLFastTimer::FTM_IDLE_CB, " Callbacks", &LLColor4::pink1, 0 }, - { LLFastTimer::FTM_RENDER, " Render", &green0, 1 }, - { LLFastTimer::FTM_PICK, " Pick", &LLColor4::purple, 1 }, - { LLFastTimer::FTM_HUD_EFFECTS, " HUD Effects", &LLColor4::orange1, 0 }, - { LLFastTimer::FTM_HUD_UPDATE, " HUD Update", &LLColor4::orange2, 0 }, - { LLFastTimer::FTM_UPDATE_SKY, " Sky Update", &LLColor4::cyan1, 0 }, - { LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 }, - { LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 1 }, - { LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 }, - { LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 }, - { LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 }, - { LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 }, - { LLFastTimer::FTM_UPDATE_AVATAR, " Avatar", &LLColor4::yellow1, 0 }, - { LLFastTimer::FTM_UPDATE_TREE, " Tree", &LLColor4::yellow2, 0 }, - { LLFastTimer::FTM_UPDATE_TERRAIN, " Terrain", &LLColor4::yellow6, 0 }, - { LLFastTimer::FTM_UPDATE_CLOUDS, " Clouds", &LLColor4::yellow7, 0 }, - { LLFastTimer::FTM_UPDATE_GRASS, " Grass", &LLColor4::yellow8, 0 }, - { LLFastTimer::FTM_UPDATE_WATER, " Water", &LLColor4::yellow9, 0 }, - { LLFastTimer::FTM_GEO_LIGHT, " Lighting", &LLColor4::yellow1, 0 }, - { LLFastTimer::FTM_GEO_SHADOW, " Shadow", &LLColor4::black, 0 }, - { LLFastTimer::FTM_UPDATE_PARTICLES, " Particles", &LLColor4::blue5, 0 }, - { LLFastTimer::FTM_GEO_RESERVE, " Reserve", &LLColor4::blue6, 0 }, - { LLFastTimer::FTM_UPDATE_LIGHTS, " Lights", &LLColor4::yellow2, 0 }, - { LLFastTimer::FTM_GEO_SKY, " Sky", &LLColor4::yellow3, 0 }, - { LLFastTimer::FTM_UPDATE_WLPARAM, " Windlight Param",&LLColor4::magenta2, 0 }, - { LLFastTimer::FTM_CULL, " Object Cull", &LLColor4::blue2, 1 }, - { LLFastTimer::FTM_CULL_REBOUND, " Rebound", &LLColor4::blue3, 0 }, - { LLFastTimer::FTM_FRUSTUM_CULL, " Frustum Cull", &LLColor4::blue4, 0 }, - { LLFastTimer::FTM_OCCLUSION_READBACK, " Occlusion Read", &LLColor4::red2, 0 }, - { LLFastTimer::FTM_IMAGE_UPDATE, " Image Update", &LLColor4::yellow4, 1 }, - { LLFastTimer::FTM_IMAGE_CREATE, " Image CreateGL",&LLColor4::yellow5, 0 }, - { LLFastTimer::FTM_IMAGE_DECODE, " Image Decode", &LLColor4::yellow6, 0 }, - { LLFastTimer::FTM_IMAGE_MARK_DIRTY, " Dirty Textures",&LLColor4::red1, 0 }, - { LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 }, - { LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable", &LLColor4::orange2, 0 }, - { LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort", &LLColor4::orange3, 0 }, - { LLFastTimer::FTM_REBUILD_OCCLUSION_VB," Occlusion", &LLColor4::cyan5, 0 }, - { LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild", &LLColor4::red4, 0 }, - { LLFastTimer::FTM_REBUILD_VOLUME_VB, " Volume", &LLColor4::blue1, 0 }, -// { LLFastTimer::FTM_REBUILD_NONE_VB, " Unknown", &LLColor4::cyan5, 0 }, -// { LLFastTimer::FTM_REBUILD_BRIDGE_VB, " Bridge", &LLColor4::blue2, 0 }, -// { LLFastTimer::FTM_REBUILD_HUD_VB, " HUD", &LLColor4::blue3, 0 }, - { LLFastTimer::FTM_REBUILD_TERRAIN_VB, " Terrain", &LLColor4::blue4, 0 }, -// { LLFastTimer::FTM_REBUILD_WATER_VB, " Water", &LLColor4::blue5, 0 }, -// { LLFastTimer::FTM_REBUILD_TREE_VB, " Tree", &LLColor4::cyan1, 0 }, - { LLFastTimer::FTM_REBUILD_PARTICLE_VB, " Particle", &LLColor4::cyan2, 0 }, -// { LLFastTimer::FTM_REBUILD_CLOUD_VB, " Cloud", &LLColor4::cyan3, 0 }, - { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass", &LLColor4::cyan4, 0 }, - { LLFastTimer::FTM_SHADOW_RENDER, " Shadow", &LLColor4::green5, 1 }, - { LLFastTimer::FTM_SHADOW_SIMPLE, " Simple", &LLColor4::yellow2, 1 }, - { LLFastTimer::FTM_SHADOW_ALPHA, " Alpha", &LLColor4::yellow6, 1 }, - { LLFastTimer::FTM_SHADOW_TERRAIN, " Terrain", &LLColor4::green6, 1 }, - { LLFastTimer::FTM_SHADOW_AVATAR, " Avatar", &LLColor4::yellow1, 1 }, - { LLFastTimer::FTM_SHADOW_TREE, " Tree", &LLColor4::yellow8, 1 }, - { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 }, - { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 1 }, - { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 1 }, - { LLFastTimer::FTM_RENDER_TERRAIN, " Terrain", &LLColor4::green6, 0 }, - { LLFastTimer::FTM_RENDER_CHARACTERS, " Avatars", &LLColor4::yellow1, 0 }, - { LLFastTimer::FTM_RENDER_SIMPLE, " Simple", &LLColor4::yellow2, 0 }, - { LLFastTimer::FTM_RENDER_FULLBRIGHT, " Fullbright", &LLColor4::yellow5, 0 }, - { LLFastTimer::FTM_RENDER_GLOW, " Glow", &LLColor4::orange1, 0 }, - { LLFastTimer::FTM_RENDER_GRASS, " Grass", &LLColor4::yellow6, 0 }, - { LLFastTimer::FTM_RENDER_INVISIBLE, " Invisible", &LLColor4::red2, 0 }, - { LLFastTimer::FTM_RENDER_SHINY, " Shiny", &LLColor4::yellow3, 0 }, - { LLFastTimer::FTM_RENDER_BUMP, " Bump", &LLColor4::yellow4, 0 }, - { LLFastTimer::FTM_RENDER_TREES, " Trees", &LLColor4::yellow8, 0 }, - { LLFastTimer::FTM_RENDER_OCCLUSION, " Occlusion", &LLColor4::red1, 0 }, - { LLFastTimer::FTM_RENDER_CLOUDS, " Clouds", &LLColor4::yellow5, 0 }, - { LLFastTimer::FTM_RENDER_ALPHA, " Alpha", &LLColor4::yellow6, 0 }, - { LLFastTimer::FTM_RENDER_HUD, " HUD", &LLColor4::yellow7, 0 }, - { LLFastTimer::FTM_RENDER_WATER, " Water", &LLColor4::yellow9, 0 }, - { LLFastTimer::FTM_RENDER_WL_SKY, " WL Sky", &LLColor4::blue3, 0 }, - { LLFastTimer::FTM_RENDER_FAKE_VBO_UPDATE," Fake VBO update", &LLColor4::red2, 0 }, - { LLFastTimer::FTM_RENDER_BLOOM, " Bloom", &LLColor4::blue4, 0 }, - { LLFastTimer::FTM_RENDER_BLOOM_FBO, " First FBO", &LLColor4::blue, 0 }, - { LLFastTimer::FTM_RENDER_UI, " UI", &LLColor4::cyan4, 1 }, - { LLFastTimer::FTM_RENDER_TIMER, " Timers", &LLColor4::cyan5, 1, 0 }, - { LLFastTimer::FTM_RENDER_FONTS, " Fonts", &LLColor4::pink1, 0 }, - { LLFastTimer::FTM_SWAP, " Swap", &LLColor4::pink2, 0 }, - { LLFastTimer::FTM_CLIENT_COPY, " Client Copy", &LLColor4::red1, 1}, - -#if 0 || !LL_RELEASE_FOR_DOWNLOAD - { LLFastTimer::FTM_TEMP1, " Temp1", &LLColor4::red1, 0 }, - { LLFastTimer::FTM_TEMP2, " Temp2", &LLColor4::magenta1, 0 }, - { LLFastTimer::FTM_TEMP3, " Temp3", &LLColor4::red2, 0 }, - { LLFastTimer::FTM_TEMP4, " Temp4", &LLColor4::magenta2, 0 }, - { LLFastTimer::FTM_TEMP5, " Temp5", &LLColor4::red3, 0 }, - { LLFastTimer::FTM_TEMP6, " Temp6", &LLColor4::magenta3, 0 }, - { LLFastTimer::FTM_TEMP7, " Temp7", &LLColor4::red4, 0 }, - { LLFastTimer::FTM_TEMP8, " Temp8", &LLColor4::magenta4, 0 }, -#endif - - { LLFastTimer::FTM_OTHER, " Other", &red0 } -}; -static int ft_display_didcalc = 0; -static const int FTV_DISPLAY_NUM = LL_ARRAY_SIZE(ft_display_table); +//static const int FTV_DISPLAY_NUM = (sizeof(ft_display_table)/sizeof(ft_display_table[0])); +static S32 FTV_NUM_TIMERS; +const S32 FTV_MAX_DEPTH = 8; + +std::vector<LLFastTimer::NamedTimer*> ft_display_idx; // line of table entry for display purposes (for collapse) + +typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_iterator_t; -S32 ft_display_idx[FTV_DISPLAY_NUM]; // line of table entry for display purposes (for collapse) +BOOL LLFastTimerView::sAnalyzePerformance = FALSE; + +static timer_tree_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id) +{ + return timer_tree_iterator_t(&id, + boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1), + boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1)); +} + +static timer_tree_iterator_t end_timer_tree() +{ + return timer_tree_iterator_t(); +} -LLFastTimerView::LLFastTimerView(const std::string& name, const LLRect& rect) - : LLFloater(name, rect, std::string("Fast Timers")) +LLFastTimerView::LLFastTimerView(const LLRect& rect) +: LLFloater(LLSD()), + mHoverTimer(NULL) { + setRect(rect); setVisible(FALSE); mDisplayMode = 0; mAvgCountTotal = 0; mMaxCountTotal = 0; - mDisplayCenter = 1; + mDisplayCenter = ALIGN_CENTER; mDisplayCalls = 0; mDisplayHz = 0; mScrollIndex = 0; - mHoverIndex = -1; + mHoverID = NULL; mHoverBarIndex = -1; - mBarStart = new S32[(MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM]; - memset(mBarStart, 0, (MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM * sizeof(S32)); - mBarEnd = new S32[(MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM]; - memset(mBarEnd, 0, (MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM * sizeof(S32)); - mSubtractHidden = 0; + FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount(); mPrintStats = -1; - - // One-time setup - if (!ft_display_didcalc) - { - int pidx[FTV_DISPLAY_NUM]; - int pdisabled[FTV_DISPLAY_NUM]; - for (S32 i=0; i < FTV_DISPLAY_NUM; i++) - { - int level = 0; - const char *text = ft_display_table[i].desc; - while(text[0] == ' ') - { - text++; - level++; - } - llassert(level < FTV_DISPLAY_NUM); - ft_display_table[i].desc = text; - ft_display_table[i].level = level; - if (level > 0) - { - ft_display_table[i].parent = pidx[level-1]; - if (pdisabled[level-1]) - { - ft_display_table[i].disabled = 3; - } - } - else - { - ft_display_table[i].parent = -1; - } - ft_display_idx[i] = i; - pidx[level] = i; - pdisabled[level] = ft_display_table[i].disabled; - } - ft_display_didcalc = 1; - } } -LLFastTimerView::~LLFastTimerView() -{ - delete[] mBarStart; - delete[] mBarEnd; -} BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if (mBarRect.pointInRect(x, y)) + if (mHoverTimer ) + { + // right click collapses timers + if (!mHoverTimer->getCollapsed()) + { + mHoverTimer->setCollapsed(true); + } + else if (mHoverTimer->getParent()) + { + mHoverTimer->getParent()->setCollapsed(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 = bar_idx; -// return TRUE; // for now, pass all mouse events through } return FALSE; } -S32 LLFastTimerView::getLegendIndex(S32 y) +LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y) { S32 idx = (getRect().getHeight() - y) / ((S32) LLFontGL::getFontMonospace()->getLineHeight()+2) - 5; - if (idx >= 0 && idx < FTV_DISPLAY_NUM) + + if (idx >= 0 && idx < (S32)ft_display_idx.size()) { return ft_display_idx[idx]; } - return -1; + return NULL; } BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) { if (x < mBarRect.mLeft) { - S32 legend_index = getLegendIndex(y); - if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM) + LLFastTimer::NamedTimer* idp = getLegendID(y); + if (idp) { - S32 disabled = ft_display_table[legend_index].disabled; - if (++disabled > 2) - disabled = 0; - ft_display_table[legend_index].disabled = disabled; - S32 level = ft_display_table[legend_index].level; - - // propagate enable/disable to all children - legend_index++; - while (legend_index < FTV_DISPLAY_NUM && ft_display_table[legend_index].level > level) - { - ft_display_table[legend_index].disabled = disabled ? 3 : 0; - legend_index++; - } + idp->setCollapsed(!idp->getCollapsed()); } } + else if (mHoverTimer) + { + //left click drills down by expanding timers + mHoverTimer->setCollapsed(false); + } else if (mask & MASK_ALT) { - if (mask & MASK_SHIFT) - { - mSubtractHidden = !mSubtractHidden; - } - else if (mask & MASK_CONTROL) + if (mask & MASK_CONTROL) { mDisplayHz = !mDisplayHz; } @@ -345,8 +167,7 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) } else if (mask & MASK_CONTROL) { - if (++mDisplayCenter > 2) - mDisplayCenter = 0; + mDisplayCenter = (ChildAlignment)((mDisplayCenter + 1) % ALIGN_COUNT); } else { @@ -367,13 +188,15 @@ BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask) return FALSE; } - BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) { + mHoverTimer = NULL; + mHoverID = NULL; + if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y)) { - mHoverIndex = -1; - mHoverBarIndex = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight()); + mHoverBarIndex = llmin(LLFastTimer::getCurFrameIndex() - 1, + MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight())); if (mHoverBarIndex == 0) { return TRUE; @@ -382,39 +205,89 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) { mHoverBarIndex = 0; } - for (S32 i = 0; i < FTV_DISPLAY_NUM; i++) + + S32 i = 0; + for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer()); + it != end_timer_tree(); + ++it, ++i) { - if (x > mBarStart[mHoverBarIndex * FTV_DISPLAY_NUM + i] && - x < mBarEnd[mHoverBarIndex * FTV_DISPLAY_NUM + i] && - ft_display_table[i].disabled <= 1) + // is mouse over bar for this timer? + if (x > mBarStart[mHoverBarIndex][i] && + x < mBarEnd[mHoverBarIndex][i]) { - mHoverIndex = i; + mHoverID = (*it); + mHoverTimer = (*it); + mToolTipRect.set(mBarStart[mHoverBarIndex][i], + mBarRect.mBottom + llround(((F32)(MAX_VISIBLE_HISTORY - mHoverBarIndex + 1)) * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f))), + mBarEnd[mHoverBarIndex][i], + mBarRect.mBottom + llround((F32)(MAX_VISIBLE_HISTORY - mHoverBarIndex) * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f)))); + } + + if ((*it)->getCollapsed()) + { + it.skipDescendants(); } } } else if (x < mBarRect.mLeft) { - S32 legend_index = getLegendIndex(y); - if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM) + LLFastTimer::NamedTimer* timer_id = getLegendID(y); + if (timer_id) { - mHoverIndex = legend_index; + mHoverID = timer_id; } } return FALSE; } + +BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +{ + if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y)) + { + // tooltips for timer bars + if (mHoverTimer) + { + localRectToScreen(mToolTipRect, sticky_rect_screen); + msg = mHoverTimer->getToolTip(LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex); + return TRUE; + } + } + else + { + // tooltips for timer legend + if (x < mBarRect.mLeft) + { + LLFastTimer::NamedTimer* idp = getLegendID(y); + if (idp) + { + msg = idp->getToolTip(); + return TRUE; + } + } + + } + + return FALSE; +} + BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks) { LLFastTimer::sPauseHistory = TRUE; mScrollIndex = llclamp(mScrollIndex - clicks, - 0, llmin(LLFastTimer::sLastFrameIndex, (S32)LLFastTimer::FTM_HISTORY_NUM-MAX_VISIBLE_HISTORY)); + 0, + llmin(LLFastTimer::getLastFrameIndex(), (S32)LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY)); return TRUE; } +static LLFastTimer::DeclareTimer FTM_RENDER_TIMER("Timers", true); + +static std::map<LLFastTimer::NamedTimer*, LLColor4> sTimerColors; + void LLFastTimerView::draw() { - LLFastTimer t(LLFastTimer::FTM_RENDER_TIMER); + LLFastTimer t(FTM_RENDER_TIMER); std::string tdesc; @@ -433,47 +306,9 @@ void LLFastTimerView::draw() S32 texth, textw; LLPointer<LLUIImage> box_imagep = LLUI::getUIImage("rounded_square.tga"); - // Make sure all timers are accounted for - // Set 'FTM_OTHER' to unaccounted ticks last frame - { - S32 display_timer[LLFastTimer::FTM_NUM_TYPES]; - S32 hidx = LLFastTimer::sLastFrameIndex % LLFastTimer::FTM_HISTORY_NUM; - for (S32 i=0; i < LLFastTimer::FTM_NUM_TYPES; i++) - { - display_timer[i] = 0; - } - for (S32 i=0; i < FTV_DISPLAY_NUM; i++) - { - S32 tidx = ft_display_table[i].timer; - display_timer[tidx] = 1; - } - LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] = 0; - LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] = 0; - for (S32 tidx = 0; tidx < LLFastTimer::FTM_NUM_TYPES; tidx++) - { - U64 counts = LLFastTimer::sCountHistory[hidx][tidx]; - if (counts > 0 && display_timer[tidx] == 0) - { - LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] += counts; - LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] += 1; - } - } - LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] = 0; - LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] = 0; - for (S32 h = 0; h < LLFastTimer::FTM_HISTORY_NUM; h++) - { - LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] += LLFastTimer::sCountHistory[h][LLFastTimer::FTM_OTHER]; - LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] += LLFastTimer::sCallHistory[h][LLFastTimer::FTM_OTHER]; - } - LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] /= LLFastTimer::FTM_HISTORY_NUM; - LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] /= LLFastTimer::FTM_HISTORY_NUM; - } - // Draw the window background - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); - } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); S32 xleft = margin; S32 ytop = margin; @@ -512,148 +347,135 @@ void LLFastTimerView::draw() y -= (texth + 2); } - // Calc the total ticks - S32 histmax = llmin(LLFastTimer::sLastFrameIndex+1, MAX_VISIBLE_HISTORY); - U64 ticks_sum[LLFastTimer::FTM_HISTORY_NUM+1][FTV_DISPLAY_NUM]; - for (S32 j=-1; j<LLFastTimer::FTM_HISTORY_NUM; j++) - { - S32 hidx; - if (j >= 0) - hidx = (LLFastTimer::sLastFrameIndex+j) % LLFastTimer::FTM_HISTORY_NUM; - else - hidx = -1; - - // calculate tick info by adding child ticks to parents - for (S32 i=0; i < FTV_DISPLAY_NUM; i++) - { - if (mSubtractHidden && ft_display_table[i].disabled > 1) - { - continue; - } - // Get ticks - S32 tidx = ft_display_table[i].timer; - if (hidx >= 0) - ticks_sum[j+1][i] = LLFastTimer::sCountHistory[hidx][tidx]; - else - ticks_sum[j+1][i] = LLFastTimer::sCountAverage[tidx]; - S32 pidx = ft_display_table[i].parent; - // Add ticks to parents - while (pidx >= 0) - { - ticks_sum[j+1][pidx] += ticks_sum[j+1][i]; - pidx = ft_display_table[pidx].parent; - } - } - } + S32 histmax = llmin(LLFastTimer::getLastFrameIndex()+1, MAX_VISIBLE_HISTORY); // Draw the legend - - S32 legendwidth = 0; xleft = margin; ytop = y; y -= (texth + 2); - S32 cur_line = 0; - S32 display_line[FTV_DISPLAY_NUM]; - for (S32 i=0; i<FTV_DISPLAY_NUM; i++) + sTimerColors[&LLFastTimer::NamedTimer::getRootNamedTimer()] = LLColor4::grey; + + F32 hue = 0.f; + + for (timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer()); + it != timer_tree_iterator_t(); + ++it) { - S32 disabled = ft_display_table[i].disabled; - if (disabled == 3) - { - continue; // skip row - } - display_line[i] = cur_line; - ft_display_idx[cur_line] = i; - cur_line++; - S32 level = ft_display_table[i].level; - S32 parent = ft_display_table[i].parent; - - x = xleft; + LLFastTimer::NamedTimer* idp = (*it); - left = x; right = x + texth; - top = y; bottom = y - texth; - S32 scale_offset = 0; - if (i == mHoverIndex) - { - scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f); - } - gl_rect_2d(left - scale_offset, top + scale_offset, right + scale_offset, bottom - scale_offset, *ft_display_table[i].color); + const F32 HUE_INCREMENT = 0.23f; + hue = fmodf(hue + HUE_INCREMENT, 1.f); + // saturation increases with depth + F32 saturation = clamp_rescale((F32)idp->getDepth(), 0.f, 3.f, 0.f, 1.f); + // lightness alternates with depth + F32 lightness = idp->getDepth() % 2 ? 0.5f : 0.6f; - int tidx = ft_display_table[i].timer; - F32 ms = 0; - S32 calls = 0; - if (mHoverBarIndex > 0 && mHoverIndex >= 0) - { - S32 hidx = (LLFastTimer::sLastFrameIndex + (mHoverBarIndex - 1) - mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM; - S32 bidx = LLFastTimer::FTM_HISTORY_NUM - mScrollIndex - mHoverBarIndex; - U64 ticks = ticks_sum[bidx+1][i]; // : LLFastTimer::sCountHistory[hidx][tidx]; - ms = (F32)((F64)ticks * iclock_freq); - calls = (S32)LLFastTimer::sCallHistory[hidx][tidx]; - } - else - { - U64 ticks = ticks_sum[0][i]; - ms = (F32)((F64)ticks * iclock_freq); - calls = (S32)LLFastTimer::sCallAverage[tidx]; - } - if (mDisplayCalls) - { - tdesc = llformat("%s (%d)",ft_display_table[i].desc,calls); - } - else - { - tdesc = llformat("%s [%.1f]",ft_display_table[i].desc,ms); - } - dx = (texth+4) + level*8; + LLColor4 child_color; + child_color.setHSL(hue, saturation, lightness); - LLColor4 color = disabled > 1 ? LLColor4::grey : LLColor4::white; - if (level > 0) + sTimerColors[idp] = child_color; + } + + const S32 LEGEND_WIDTH = 220; + { + LLLocalClipRect clip(LLRect(margin, y, LEGEND_WIDTH, margin)); + S32 cur_line = 0; + ft_display_idx.clear(); + std::map<LLFastTimer::NamedTimer*, S32> display_line; + for (timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer()); + it != timer_tree_iterator_t(); + ++it) { - S32 line_start_y = (top + bottom) / 2; - S32 line_end_y = line_start_y + ((texth + 2) * (display_line[i] - display_line[parent])) - (texth / 2); - gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color); - S32 line_x = x + (texth + 4) + ((level - 1) * 8); - gl_line_2d(line_x, line_start_y, line_x, line_end_y, color); - if (disabled == 1) + LLFastTimer::NamedTimer* idp = (*it); + display_line[idp] = cur_line; + ft_display_idx.push_back(idp); + cur_line++; + + x = xleft; + + left = x; right = x + texth; + top = y; bottom = y - texth; + S32 scale_offset = 0; + if (idp == mHoverID) { - gl_line_2d(line_x+4, line_start_y-3, line_x+4, line_start_y+4, color); + scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f); } - } + gl_rect_2d(left - scale_offset, top + scale_offset, right + scale_offset, bottom - scale_offset, sTimerColors[idp]); - x += dx; - BOOL is_child_of_hover_item = (i == mHoverIndex); - S32 next_parent = ft_display_table[i].parent; - while(!is_child_of_hover_item && next_parent >= 0) - { - is_child_of_hover_item = (mHoverIndex == next_parent); - next_parent = ft_display_table[next_parent].parent; - } + F32 ms = 0; + S32 calls = 0; + if (mHoverBarIndex > 0 && mHoverID) + { + S32 hidx = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex; + U64 ticks = idp->getHistoricalCount(hidx); + ms = (F32)((F64)ticks * iclock_freq); + calls = (S32)idp->getHistoricalCalls(hidx); + } + else + { + U64 ticks = idp->getCountAverage(); + ms = (F32)((F64)ticks * iclock_freq); + calls = (S32)idp->getCallAverage(); + } - if (is_child_of_hover_item) - { - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD); - } - else - { - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP); - } - y -= (texth + 2); + if (mDisplayCalls) + { + tdesc = llformat("%s (%d)",idp->getName().c_str(),calls); + } + else + { + tdesc = llformat("%s [%.1f]",idp->getName().c_str(),ms); + } + dx = (texth+4) + idp->getDepth()*8; - textw = dx + LLFontGL::getFontMonospace()->getWidth(std::string(ft_display_table[i].desc)) + 40; - if (textw > legendwidth) - legendwidth = textw; - } - for (S32 i=cur_line; i<FTV_DISPLAY_NUM; i++) - { - ft_display_idx[i] = -1; + LLColor4 color = LLColor4::white; + if (idp->getDepth() > 0) + { + S32 line_start_y = (top + bottom) / 2; + S32 line_end_y = line_start_y + ((texth + 2) * (cur_line - display_line[idp->getParent()])) - texth; + gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color); + S32 line_x = x + (texth + 4) + ((idp->getDepth() - 1) * 8); + gl_line_2d(line_x, line_start_y, line_x, line_end_y, color); + if (idp->getCollapsed() && !idp->getChildren().empty()) + { + gl_line_2d(line_x+4, line_start_y-3, line_x+4, line_start_y+4, color); + } + } + + x += dx; + BOOL is_child_of_hover_item = (idp == mHoverID); + LLFastTimer::NamedTimer* next_parent = idp->getParent(); + while(!is_child_of_hover_item && next_parent) + { + is_child_of_hover_item = (mHoverID == next_parent); + next_parent = next_parent->getParent(); + } + + LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, + x, y, + color, + LLFontGL::LEFT, LLFontGL::TOP, + is_child_of_hover_item ? LLFontGL::BOLD : LLFontGL::NORMAL); + + y -= (texth + 2); + + textw = dx + LLFontGL::getFontMonospace()->getWidth(idp->getName()) + 40; + + if (idp->getCollapsed()) + { + it.skipDescendants(); + } + } } - xleft += legendwidth + 8; + + xleft += LEGEND_WIDTH + 8; // ytop = ytop; // update rectangle that includes timer bars mBarRect.mLeft = xleft; - mBarRect.mRight = getRect().mRight - xleft; + mBarRect.mRight = getRect().getWidth(); mBarRect.mTop = ytop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4); mBarRect.mBottom = margin + LINE_GRAPH_HEIGHT; @@ -665,25 +487,18 @@ void LLFastTimerView::draw() barw = width - xleft - margin; // Draw the history bars - if (LLFastTimer::sLastFrameIndex >= 0) + if (LLFastTimer::getLastFrameIndex() >= 0) { + LLLocalClipRect clip(LLRect(xleft, ytop - margin, getRect().getWidth() - margin, margin)); + U64 totalticks; if (!LLFastTimer::sPauseHistory) { - U64 ticks = 0; - int hidx = (LLFastTimer::sLastFrameIndex - mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM; - for (S32 i=0; i<FTV_DISPLAY_NUM; i++) - { - if (mSubtractHidden && ft_display_table[i].disabled > 1) - { - continue; - } - int tidx = ft_display_table[i].timer; - ticks += LLFastTimer::sCountHistory[hidx][tidx]; - } - if (LLFastTimer::sCurFrameIndex >= 10) + U64 ticks = LLFastTimer::NamedTimer::getRootNamedTimer().getHistoricalCount(mScrollIndex); + + if (LLFastTimer::getCurFrameIndex() >= 10) { - U64 framec = LLFastTimer::sCurFrameIndex; + U64 framec = LLFastTimer::getCurFrameIndex(); U64 avg = (U64)mAvgCountTotal; mAvgCountTotal = (avg*framec + ticks) / (framec + 1); if (ticks > mMaxCountTotal) @@ -691,11 +506,13 @@ void LLFastTimerView::draw() mMaxCountTotal = ticks; } } -#if 1 + if (ticks < mAvgCountTotal/100 || ticks > mAvgCountTotal*100) - LLFastTimer::sResetHistory = 1; -#endif - if (LLFastTimer::sCurFrameIndex < 10 || LLFastTimer::sResetHistory) + { + LLFastTimer::sResetHistory = true; + } + + if (LLFastTimer::getCurFrameIndex() < 10 || LLFastTimer::sResetHistory) { mAvgCountTotal = ticks; mMaxCountTotal = ticks; @@ -716,16 +533,8 @@ void LLFastTimerView::draw() totalticks = 0; for (S32 j=0; j<histmax; j++) { - U64 ticks = 0; - for (S32 i=0; i<FTV_DISPLAY_NUM; i++) - { - if (mSubtractHidden && ft_display_table[i].disabled > 1) - { - continue; - } - int tidx = ft_display_table[i].timer; - ticks += LLFastTimer::sCountHistory[j][tidx]; - } + U64 ticks = LLFastTimer::NamedTimer::getRootNamedTimer().getHistoricalCount(j); + if (ticks > totalticks) totalticks = ticks; } @@ -798,18 +607,23 @@ void LLFastTimerView::draw() gl_rect_2d(graph_rect, FALSE); } + mBarStart.clear(); + mBarEnd.clear(); + // Draw bars for each history entry // Special: -1 = show running average gGL.getTexUnit(0)->bind(box_imagep->getImage()); for (S32 j=-1; j<histmax && y > LINE_GRAPH_HEIGHT; j++) { - int sublevel_dx[FTV_DISPLAY_NUM+1]; - int sublevel_left[FTV_DISPLAY_NUM+1]; - int sublevel_right[FTV_DISPLAY_NUM+1]; + mBarStart.push_back(std::vector<S32>()); + mBarEnd.push_back(std::vector<S32>()); + int sublevel_dx[FTV_MAX_DEPTH]; + int sublevel_left[FTV_MAX_DEPTH]; + int sublevel_right[FTV_MAX_DEPTH]; S32 tidx; if (j >= 0) { - tidx = LLFastTimer::FTM_HISTORY_NUM - j - 1 - mScrollIndex; + tidx = LLFastTimer::NamedTimer::HISTORY_NUM - j - 1 - mScrollIndex; } else { @@ -819,88 +633,75 @@ void LLFastTimerView::draw() x = xleft; // draw the bars for each stat - int xpos[FTV_DISPLAY_NUM+1]; - int deltax[FTV_DISPLAY_NUM+1]; - xpos[0] = xleft; + std::vector<S32> xpos; + std::vector<S32> deltax; + xpos.push_back(xleft); + + LLFastTimer::NamedTimer* prev_id = NULL; - for (S32 i = 0; i < FTV_DISPLAY_NUM; i++) + S32 i = 0; + for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer()); + it != end_timer_tree(); + ++it, ++i) { - if (ft_display_table[i].disabled > 1) - { - continue; - } - - F32 frac = (F32)ticks_sum[tidx+1][i] / (F32)totalticks; + LLFastTimer::NamedTimer* idp = (*it); + F32 frac = tidx == -1 + ? (F32)idp->getCountAverage() / (F32)totalticks + : (F32)idp->getHistoricalCount(tidx) / (F32)totalticks; dx = llround(frac * (F32)barw); - deltax[i] = dx; - - int level = ft_display_table[i].level; - int parent = ft_display_table[i].parent; - llassert(level < FTV_DISPLAY_NUM); - llassert(parent < FTV_DISPLAY_NUM); + S32 prev_delta_x = deltax.empty() ? 0 : deltax.back(); + deltax.push_back(dx); - left = xpos[level]; + int level = idp->getDepth() - 1; - S32 prev_idx = i - 1; - while (prev_idx > 0) - { - if (ft_display_table[prev_idx].disabled <= 1) - { - break; - } - prev_idx--; - } - S32 next_idx = i + 1; - while (next_idx < FTV_DISPLAY_NUM) + while ((S32)xpos.size() > level + 1) { - if (ft_display_table[next_idx].disabled <= 1) - { - break; - } - next_idx++; + xpos.pop_back(); } - + left = xpos.back(); + if (level == 0) - { + { sublevel_left[level] = xleft; sublevel_dx[level] = dx; sublevel_right[level] = sublevel_left[level] + sublevel_dx[level]; - } - else if (i==0 || ft_display_table[prev_idx].level < level) + } + else if (prev_id && prev_id->getDepth() < idp->getDepth()) { - // If we are the first entry at a new sublevel block, calc the - // total width of this sublevel and modify left to align block. - U64 sublevelticks = ticks_sum[tidx+1][i]; - for (S32 k=i+1; k<FTV_DISPLAY_NUM; k++) - { - if (ft_display_table[k].level < level) - break; - if (ft_display_table[k].disabled <= 1 && ft_display_table[k].level == level) - sublevelticks += ticks_sum[tidx+1][k]; - } - F32 subfrac = (F32)sublevelticks / (F32)totalticks; + U64 sublevelticks = 0; + + for (LLFastTimer::NamedTimer::child_const_iter it = prev_id->beginChildren(); + it != prev_id->endChildren(); + ++it) + { + sublevelticks += (tidx == -1) + ? (*it)->getCountAverage() + : (*it)->getHistoricalCount(tidx); + } + + F32 subfrac = (F32)sublevelticks / (F32)totalticks; sublevel_dx[level] = (int)(subfrac * (F32)barw + .5f); - if (mDisplayCenter == 1) // center aligned + if (mDisplayCenter == ALIGN_CENTER) { - left += (deltax[parent] - sublevel_dx[level])/2; + left += (prev_delta_x - sublevel_dx[level])/2; } - else if (mDisplayCenter == 2) // right aligned + else if (mDisplayCenter == ALIGN_RIGHT) { - left += (deltax[parent] - sublevel_dx[level]); - } + left += (prev_delta_x - sublevel_dx[level]); + } sublevel_left[level] = left; sublevel_right[level] = sublevel_left[level] + sublevel_dx[level]; } right = left + dx; - xpos[level] = right; - xpos[level+1] = left; + xpos.back() = right; + xpos.push_back(left); - mBarStart[(j + 1) * FTV_DISPLAY_NUM + i] = left; - mBarEnd[(j + 1) * FTV_DISPLAY_NUM + i] = right; + mBarStart.back().push_back(left); + mBarEnd.back().push_back(right); top = y; bottom = y - barh; @@ -908,23 +709,23 @@ void LLFastTimerView::draw() if (right > left) { //U32 rounded_edges = 0; - LLColor4 color = *ft_display_table[i].color; + LLColor4 color = sTimerColors[idp];//*ft_display_table[i].color; S32 scale_offset = 0; - BOOL is_child_of_hover_item = (i == mHoverIndex); - S32 next_parent = ft_display_table[i].parent; - while(!is_child_of_hover_item && next_parent >= 0) + BOOL is_child_of_hover_item = (idp == mHoverID); + LLFastTimer::NamedTimer* next_parent = idp->getParent(); + while(!is_child_of_hover_item && next_parent) { - is_child_of_hover_item = (mHoverIndex == next_parent); - next_parent = ft_display_table[next_parent].parent; + is_child_of_hover_item = (mHoverID == next_parent); + next_parent = next_parent->getParent(); } - if (i == mHoverIndex) + if (idp == mHoverID) { scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 3.f); //color = lerp(color, LLColor4::black, -0.4f); } - else if (mHoverIndex >= 0 && !is_child_of_hover_item) + else if (mHoverID != NULL && !is_child_of_hover_item) { color = lerp(color, LLColor4::grey, 0.8f); } @@ -935,7 +736,13 @@ void LLFastTimerView::draw() gl_segmented_rect_2d_fragment_tex(sublevel_left[level], top - level + scale_offset, sublevel_right[level], bottom + level - scale_offset, box_imagep->getTextureWidth(), box_imagep->getTextureHeight(), 16, start_fragment, end_fragment); } - + + if ((*it)->getCollapsed()) + { + it.skipDescendants(); + } + + prev_id = idp; } y -= (barh + dy); if (j < 0) @@ -970,10 +777,10 @@ void LLFastTimerView::draw() //highlight visible range { - S32 first_frame = LLFastTimer::FTM_HISTORY_NUM - mScrollIndex; + S32 first_frame = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex; S32 last_frame = first_frame - MAX_VISIBLE_HISTORY; - F32 frame_delta = ((F32) (graph_rect.getWidth()))/(LLFastTimer::FTM_HISTORY_NUM-1); + F32 frame_delta = ((F32) (graph_rect.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; @@ -996,28 +803,27 @@ void LLFastTimerView::draw() } U64 cur_max = 0; - for (S32 idx = 0; idx < FTV_DISPLAY_NUM; ++idx) + for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer()); + it != end_timer_tree(); + ++it) { - if (ft_display_table[idx].disabled > 1) - { //skip disabled timers - continue; - } + LLFastTimer::NamedTimer* idp = (*it); //fatten highlighted timer - if (mHoverIndex == idx) + if (mHoverID == idp) { gGL.flush(); glLineWidth(3); } - const F32 * col = ft_display_table[idx].color->mV; + const F32 * col = sTimerColors[idp].mV;// ft_display_table[idx].color->mV; F32 alpha = 1.f; - if (mHoverIndex >= 0 && - idx != mHoverIndex) + if (mHoverID != NULL && + idp != mHoverID) { //fade out non-hihglighted timers - if (ft_display_table[idx].parent != mHoverIndex) + if (idp->getParent() != mHoverID) { alpha = alpha_interp; } @@ -1025,9 +831,9 @@ void LLFastTimerView::draw() gGL.color4f(col[0], col[1], col[2], alpha); gGL.begin(LLRender::LINE_STRIP); - for (U32 j = 0; j < LLFastTimer::FTM_HISTORY_NUM; j++) + for (U32 j = 0; j < LLFastTimer::NamedTimer::HISTORY_NUM; j++) { - U64 ticks = ticks_sum[j+1][idx]; + U64 ticks = idp->getHistoricalCount(j); if (mDisplayHz) { @@ -1037,26 +843,31 @@ void LLFastTimerView::draw() } else if (mDisplayCalls) { - S32 tidx = ft_display_table[idx].timer; - S32 hidx = (LLFastTimer::sLastFrameIndex + j) % LLFastTimer::FTM_HISTORY_NUM; - ticks = (S32)LLFastTimer::sCallHistory[hidx][tidx]; + ticks = (S32)idp->getHistoricalCalls(j); } if (alpha == 1.f) - { //normalize to highlighted timer + { + //normalize to highlighted timer cur_max = llmax(cur_max, ticks); } - F32 x = graph_rect.mLeft + ((F32) (graph_rect.getWidth()))/(LLFastTimer::FTM_HISTORY_NUM-1)*j; + 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; gGL.vertex2f(x,y); } gGL.end(); - if (mHoverIndex == idx) + if (mHoverID == idp) { gGL.flush(); glLineWidth(1); } + + if (idp->getCollapsed()) + { + //skip hidden timers + it.skipDescendants(); + } } //interpolate towards new maximum @@ -1068,12 +879,16 @@ void LLFastTimerView::draw() alpha_interp = alpha_interp + (alpha_target-alpha_interp) * dt; - if (mHoverIndex >= 0) + if (mHoverID != NULL) { x = (graph_rect.mRight + graph_rect.mLeft)/2; y = graph_rect.mBottom + 8; - LLFontGL::getFontMonospace()->renderUTF8(std::string(ft_display_table[mHoverIndex].desc), 0, x, y, LLColor4::white, + LLFontGL::getFontMonospace()->renderUTF8( + mHoverID->getName(), + 0, + x, y, + LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM); } } @@ -1083,87 +898,274 @@ void LLFastTimerView::draw() if (mPrintStats >= 0) { std::string legend_stat; - S32 stat_num; - S32 first = 1; - for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; stat_num++) + bool first = true; + for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer()); + it != end_timer_tree(); + ++it) { - if (ft_display_table[stat_num].disabled > 1) - continue; + LLFastTimer::NamedTimer* idp = (*it); + if (!first) + { legend_stat += ", "; - first=0; - legend_stat += ft_display_table[stat_num].desc; + } + first = true; + legend_stat += idp->getName(); + + if (idp->getCollapsed()) + { + it.skipDescendants(); + } } llinfos << legend_stat << llendl; std::string timer_stat; - first = 1; - for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; stat_num++) + first = true; + for(timer_tree_iterator_t it = begin_timer_tree(LLFastTimer::NamedTimer::getRootNamedTimer()); + it != end_timer_tree(); + ++it) { - S32 disabled = ft_display_table[stat_num].disabled; - if (disabled > 1) - continue; + LLFastTimer::NamedTimer* idp = (*it); + if (!first) + { timer_stat += ", "; - first=0; + } + first = false; + U64 ticks; - S32 tidx = ft_display_table[stat_num].timer; if (mPrintStats > 0) { - S32 hidx = (LLFastTimer::sLastFrameIndex+(mPrintStats-1)-mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM; - ticks = disabled >= 1 ? ticks_sum[mPrintStats][stat_num] : LLFastTimer::sCountHistory[hidx][tidx]; + S32 hidx = (mPrintStats - 1) - mScrollIndex; + ticks = idp->getHistoricalCount(hidx); } else { - ticks = disabled >= 1 ? ticks_sum[0][stat_num] : LLFastTimer::sCountAverage[tidx]; + ticks = idp->getCountAverage(); } F32 ms = (F32)((F64)ticks * iclock_freq); timer_stat += llformat("%.1f",ms); + + if (idp->getCollapsed()) + { + it.skipDescendants(); + } } llinfos << timer_stat << llendl; mPrintStats = -1; } - mHoverIndex = -1; + mHoverID = NULL; mHoverBarIndex = -1; LLView::draw(); } -F64 LLFastTimerView::getTime(LLFastTimer::EFastTimerType tidx) +F64 LLFastTimerView::getTime(const std::string& name) { - // Find table index - S32 i; - for (i=0; i<FTV_DISPLAY_NUM; i++) + const LLFastTimer::NamedTimer* timerp = LLFastTimer::getTimerByName(name); + if (timerp) { - if (tidx == ft_display_table[i].timer) + return (F64)timerp->getCountAverage() / (F64)LLFastTimer::countsPerSecond(); + } + return 0.0; +} + +//static +LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is) +{ + LLSD ret; + + LLSD cur; + + LLSD::Real total_time = 0.0; + LLSD::Integer total_frames = 0; + + while (!is.eof() && LLSDSerialize::fromXML(cur, is)) + { + for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter) { - break; + std::string label = iter->first; + + F64 time = iter->second["Time"].asReal(); + + total_time += time; + + if (time > 0.0) + { + ret[label]["TotalTime"] = ret[label]["TotalTime"].asReal() + time; + ret[label]["MaxTime"] = llmax(time, ret[label]["MaxTime"].asReal()); + + if (ret[label]["MinTime"].asReal() == 0) + { + ret[label]["MinTime"] = time; + } + else + { + ret[label]["MinTime"] = llmin(ret[label]["MinTime"].asReal(), time); + } + + LLSD::Integer samples = iter->second["Calls"].asInteger(); + + ret[label]["Samples"] = ret[label]["Samples"].asInteger() + samples; + ret[label]["MaxSamples"] = llmax(ret[label]["MaxSamples"].asInteger(), samples); + + if (ret[label]["MinSamples"].asInteger() == 0) + { + ret[label]["MinSamples"] = samples; + } + else + { + ret[label]["MinSamples"] = llmin(ret[label]["MinSamples"].asInteger(), samples); + } + } } + total_frames++; } + + ret["SessionTime"] = total_time; + ret["FrameCount"] = total_frames; + + return ret; - if (i == FTV_DISPLAY_NUM) +} + +//static +void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target, std::string output) +{ + + //analyze baseline + std::ifstream base_is(baseline.c_str()); + LLSD base = analyzePerformanceLogDefault(base_is); + base_is.close(); + + //analyze current + std::ifstream target_is(target.c_str()); + LLSD current = analyzePerformanceLogDefault(target_is); + target_is.close(); + + //output comparision + std::ofstream os(output.c_str()); + + LLSD::Real session_time = current["SessionTime"].asReal(); + + os << "Label, % Change, % of Session, Cur Min, Cur Max, Cur Mean, Cur Total, Cur Samples, Base Min, Base Max, Base Mean, Base Total, Base Samples\n"; + for (LLSD::map_iterator iter = base.beginMap(); iter != base.endMap(); ++iter) { - // walked off the end of ft_display_table without finding - // the desired timer type - llwarns << "Timer type " << tidx << " not known." << llendl; - return F64(0.0); + LLSD::String label = iter->first; + + if (current[label]["Samples"].asInteger() == 0 || + base[label]["Samples"].asInteger() == 0) + { + //cannot compare + continue; + } + LLSD::Real a = base[label]["TotalTime"].asReal() / base[label]["Samples"].asReal(); + LLSD::Real b = current[label]["TotalTime"].asReal() / base[label]["Samples"].asReal(); + + LLSD::Real diff = b-a; + + LLSD::Real perc = diff/a * 100; + + os << llformat("%s, %.2f, %.4f, %.4f, %.4f, %.4f, %.4f, %d, %.4f, %.4f, %.4f, %.4f, %d\n", + label.c_str(), + (F32) perc, + (F32) (current[label]["TotalTime"].asReal()/session_time * 100.0), + (F32) current[label]["MinTime"].asReal(), + (F32) current[label]["MaxTime"].asReal(), + (F32) b, + (F32) current[label]["TotalTime"].asReal(), + current[label]["Samples"].asInteger(), + (F32) base[label]["MinTime"].asReal(), + (F32) base[label]["MaxTime"].asReal(), + (F32) a, + (F32) base[label]["TotalTime"].asReal(), + base[label]["Samples"].asInteger()); } - S32 table_idx = i; - // Add child ticks to parent - U64 ticks = LLFastTimer::sCountAverage[tidx]; - S32 level = ft_display_table[table_idx].level; - for (i=table_idx+1; i<FTV_DISPLAY_NUM; i++) + os.flush(); + os.close(); +} + +//------------------------- +//static +LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is) +{ + LLSD ret; + LLSD cur; + + while (!is.eof() && LLSDSerialize::fromXML(cur, is)) { - if (ft_display_table[i].level <= level) + for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter) { - break; + std::string label = iter->first; + + LLMetricPerformanceTester* tester = LLMetricPerformanceTester::getTester(iter->second["Name"].asString()) ; + if(tester) + { + ret[label]["Name"] = iter->second["Name"] ; + + S32 num_of_strings = tester->getNumOfMetricStrings() ; + for(S32 index = 0 ; index < num_of_strings ; index++) + { + ret[label][ tester->getMetricString(index) ] = iter->second[ tester->getMetricString(index) ] ; + } + } } - ticks += LLFastTimer::sCountAverage[ft_display_table[i].timer]; } + + return ret; +} - return (F64)ticks / (F64)LLFastTimer::countsPerSecond(); +//static +void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target, std::string output) +{ + if(!LLMetricPerformanceTester::hasMetricPerformanceTesters()) + { + return ; + } + + //analyze baseline + std::ifstream base_is(baseline.c_str()); + LLSD base = analyzeMetricPerformanceLog(base_is); + base_is.close(); + + //analyze current + std::ifstream target_is(target.c_str()); + LLSD current = analyzeMetricPerformanceLog(target_is); + target_is.close(); + + //output comparision + std::ofstream os(output.c_str()); + + os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n"; + for(LLMetricPerformanceTester::name_tester_map_t::iterator iter = LLMetricPerformanceTester::sTesterMap.begin() ; + iter != LLMetricPerformanceTester::sTesterMap.end() ; ++iter) + { + LLMetricPerformanceTester* tester = ((LLMetricPerformanceTester*)iter->second) ; + tester->analyzePerformance(&os, &base, ¤t) ; + } + + os.flush(); + os.close(); } + +//static +void LLFastTimerView::doAnalysis(std::string baseline, std::string target, std::string output) +{ + if(LLFastTimer::sLog) + { + doAnalysisDefault(baseline, target, output) ; + return ; + } + + if(LLFastTimer::sMetricLog) + { + doAnalysisMetrics(baseline, target, output) ; + return ; + } +} + + |