diff --git a/server/TracySourceView.cpp b/server/TracySourceView.cpp index fab54dc6..3a24599a 100644 --- a/server/TracySourceView.cpp +++ b/server/TracySourceView.cpp @@ -83,6 +83,12 @@ static constexpr const char* s_CostName[] = { static constexpr SourceView::CostType s_costSeparateAfter = SourceView::CostType::SlowCache; +struct ChildStat +{ + uint64_t addr; + uint32_t count; +}; + static size_t CountHwSamples( const SortedVector& vec, const Range& range ) { @@ -180,6 +186,7 @@ SourceView::SourceView( GetWindowCallback gwcb ) , m_calcInlineStats( true ) , m_atnt( false ) , m_childCalls( false ) + , m_childCallList( false ) , m_hwSamples( true ) , m_hwSamplesRelative( true ) , m_cost( CostType::SampleCount ) @@ -1300,6 +1307,7 @@ void SourceView::RenderSymbolView( Worker& worker, View& view ) ImGui::PushItemFlag( ImGuiItemFlags_Disabled, true ); ImGui::PushStyleVar( ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f ); m_childCalls = false; + m_childCallList = false; } else if( ImGui::IsKeyDown( 'Z' ) ) { @@ -1327,6 +1335,8 @@ void SourceView::RenderSymbolView( Worker& worker, View& view ) } } ImGui::SameLine(); + SmallToggleButton( ICON_FA_EYE, m_childCallList ); + ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine(); if( m_childCalls ) @@ -1374,6 +1384,7 @@ void SourceView::RenderSymbolView( Worker& worker, View& view ) else { TextFocused( "Events:", RealToString( as.ipTotalAsm.local ) ); + m_childCallList = false; } ImGui::SameLine(); ImGui::Spacing(); @@ -1422,6 +1433,59 @@ void SourceView::RenderSymbolView( Worker& worker, View& view ) ImGui::PopStyleVar(); ImGui::Separator(); + if( m_childCallList ) + { + unordered_flat_map map; + if( m_calcInlineStats ) + { + GatherChildStats( m_symAddr, map, worker, limitView, view ); + } + else + { + GatherChildStats( m_baseAddr, map, worker, limitView, view ); + } + if( !map.empty() ) + { + TextDisabledUnformatted( "Child call distribution" ); + if( ImGui::BeginChild( "ccd", ImVec2( 0, ImGui::GetFontSize() * std::min( 4, map.size() ) + ImGui::GetStyle().WindowPadding.y ) ) ) + { + std::vector vec; + vec.reserve( map.size() ); + for( auto& v : map ) vec.emplace_back( ChildStat { v.first, v.second } ); + pdqsort_branchless( vec.begin(), vec.end(), []( const auto& lhs, const auto& rhs ) { return lhs.count > rhs.count; } ); + int idx = 1; + for( auto& v : vec ) + { + ImGui::TextDisabled( "%i.", idx++ ); + ImGui::SameLine(); + auto sd = worker.GetSymbolData( v.addr ); + const auto symName = worker.GetString( sd->name ); + if( v.addr >> 63 == 0 ) + { + ImGui::TextUnformatted( symName ); + } + else + { + TextColoredUnformatted( 0xFF8888FF, symName ); + } + ImGui::SameLine(); + char tmp[16]; + auto end = PrintFloat( tmp, tmp+16, 100.f * v.count / as.ipTotalAsm.ext, 2 ); + *end = '\0'; + ImGui::TextDisabled( "%s (%s%%)", TimeToString( v.count * worker.GetSamplingPeriod() ), tmp ); + if( ImGui::IsItemHovered() ) + { + ImGui::BeginTooltip(); + ImGui::Text( "%s samples", RealToString( v.count ) ); + ImGui::EndTooltip(); + } + } + } + ImGui::EndChild(); + ImGui::Separator(); + } + } + uint64_t jumpOut = 0; switch( m_displayMode ) { diff --git a/server/TracySourceView.hpp b/server/TracySourceView.hpp index 2365d620..4ffbde2b 100644 --- a/server/TracySourceView.hpp +++ b/server/TracySourceView.hpp @@ -223,6 +223,7 @@ private: uint64_t m_jumpPopupAddr; bool m_hwSamples, m_hwSamplesRelative; bool m_childCalls; + bool m_childCallList; CostType m_cost; SourceContents m_source;