From 0a8ec095666bd2a710f8c637ac6ab4adde8f018f Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 5 Jun 2021 11:01:05 -0700 Subject: [PATCH 01/15] Introduce View::IsZoneReentry() These two methods can search a timeline to determine whether a given ZoneEvent is the only appearance of the given zone on the current thread stack, or a re-entry. --- server/TracyView.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++ server/TracyView.hpp | 2 + 2 files changed, 89 insertions(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index ab09a86e..9c079234 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -17523,6 +17523,93 @@ const ZoneEvent* View::GetZoneParent( const ZoneEvent& zone, uint64_t tid ) cons return nullptr; } +bool View::IsZoneReentry( const ZoneEvent& zone ) const +{ +#ifndef TRACY_NO_STATISTICS + if( m_worker.AreSourceLocationZonesReady() ) + { + auto& slz = m_worker.GetZonesForSourceLocation( zone.SrcLoc() ); + if( !slz.zones.empty() ) + { + auto it = std::lower_bound( slz.zones.begin(), slz.zones.end(), zone.Start(), [] ( const auto& lhs, const auto& rhs ) { return lhs.Zone()->Start() < rhs; } ); + if( it != slz.zones.end() && it->Zone() == &zone ) + { + return IsZoneReentry( zone, m_worker.DecompressThread( it->Thread() ) ); + } + } + } +#endif + + for( const auto& thread : m_worker.GetThreadData() ) + { + const ZoneEvent* parent = nullptr; + const Vector>* timeline = &thread->timeline; + if( timeline->empty() ) continue; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); + if( it != vec->begin() ) --it; + if( zone.IsEndValid() && it->Start() > zone.End() ) break; + if( it == &zone ) return false; + if( !it->HasChildren() ) break; + parent = it; + if (parent->SrcLoc() == zone.SrcLoc() ) return true; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); + if( it != timeline->begin() ) --it; + if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; + if( *it == &zone ) return false; + if( !(*it)->HasChildren() ) break; + parent = *it; + if (parent->SrcLoc() == zone.SrcLoc() ) return true; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + } + } + return false; +} + +bool View::IsZoneReentry( const ZoneEvent& zone, uint64_t tid ) const +{ + const auto thread = m_worker.GetThreadData( tid ); + const ZoneEvent* parent = nullptr; + const Vector>* timeline = &thread->timeline; + if( timeline->empty() ) return false; + for(;;) + { + if( timeline->is_magic() ) + { + auto vec = (Vector*)timeline; + auto it = std::upper_bound( vec->begin(), vec->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r.Start(); } ); + if( it != vec->begin() ) --it; + if( zone.IsEndValid() && it->Start() > zone.End() ) break; + if( it == &zone ) return false; + if( !it->HasChildren() ) break; + parent = it; + if (parent->SrcLoc() == zone.SrcLoc() ) return true; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + else + { + auto it = std::upper_bound( timeline->begin(), timeline->end(), zone.Start(), [] ( const auto& l, const auto& r ) { return l < r->Start(); } ); + if( it != timeline->begin() ) --it; + if( zone.IsEndValid() && (*it)->Start() > zone.End() ) break; + if( *it == &zone ) return false; + if( !(*it)->HasChildren() ) break; + parent = *it; + if (parent->SrcLoc() == zone.SrcLoc() ) return true; + timeline = &m_worker.GetZoneChildren( parent->Child() ); + } + } + return false; +} + const GpuEvent* View::GetZoneParent( const GpuEvent& zone ) const { for( const auto& ctx : m_worker.GetGpuData() ) diff --git a/server/TracyView.hpp b/server/TracyView.hpp index a5b31bac..66eb97a3 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -250,6 +250,8 @@ private: const ZoneEvent* GetZoneParent( const ZoneEvent& zone ) const; const ZoneEvent* GetZoneParent( const ZoneEvent& zone, uint64_t tid ) const; + bool IsZoneReentry( const ZoneEvent& zone ) const; + bool IsZoneReentry( const ZoneEvent& zone, uint64_t tid ) const; const GpuEvent* GetZoneParent( const GpuEvent& zone ) const; const ThreadData* GetZoneThreadData( const ZoneEvent& zone ) const; uint64_t GetZoneThread( const ZoneEvent& zone ) const; From 1f0b4656f4621223a4df8b6829a432f7b56b3597 Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 5 Jun 2021 11:06:32 -0700 Subject: [PATCH 02/15] Introduce SrcLocCountMap Add to ThreadData a map from source location to a counter, which will be used to keep track of the number of appearances of zones with the corresponding source locations on each thread's stack. --- server/TracyEvent.hpp | 49 ++++++++++++++++++++++++++++++++++++++++++ server/TracyWorker.cpp | 1 + 2 files changed, 50 insertions(+) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 84547ce2..1f349a06 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -587,12 +587,57 @@ enum { GhostZoneSize = sizeof( GhostZone ) }; #pragma pack() +using SrcLocCountMap = unordered_flat_map; + +tracy_force_inline void IncSrcLocCount(SrcLocCountMap& countMap, int16_t srcloc) +{ + const auto it = countMap.find( srcloc ); + if( it == countMap.end() ) + { + countMap.emplace( srcloc, 1 ); + return; + } + + assert( it->second != 0 ); + it->second++; +} + +tracy_force_inline bool DecSrcLocCount(SrcLocCountMap& countMap, int16_t srcloc) +{ + const auto it = countMap.find( srcloc ); + assert( it != countMap.end() ); + assert( it->second != 0 ); + + if( it->second == 1 ) + { + countMap.erase( it ); + return false; + } + + it->second--; + return true; +} + +tracy_force_inline bool HasSrcLocCount(SrcLocCountMap& countMap, int16_t srcloc) +{ + const auto it = countMap.find( srcloc ); + + if( it != countMap.end() ) + { + assert( it->second != 0 ); + return true; + } + + return false; +} + struct ThreadData { uint64_t id; uint64_t count; Vector> timeline; Vector> stack; + SrcLocCountMap stackCount; Vector> messages; uint32_t nextZoneId; Vector zoneIdStack; @@ -604,6 +649,10 @@ struct ThreadData Vector samples; SampleData pendingSample; uint64_t kernelSampleCnt; + + tracy_force_inline void IncStackCount(int16_t srcloc) { IncSrcLocCount( stackCount, srcloc ); } + + tracy_force_inline bool DecStackCount(int16_t srcloc) { return DecSrcLocCount( stackCount, srcloc ); } }; struct GpuCtxThreadData diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index a55aae86..1b860248 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -2006,6 +2006,7 @@ Worker::~Worker() { v->timeline.~Vector(); v->stack.~Vector(); + v->stackCount.~Table(); v->messages.~Vector(); v->zoneIdStack.~Vector(); v->samples.~Vector(); From c90e39e06e172bb15aa698c51223bb0bf9405b3a Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 5 Jun 2021 11:13:57 -0700 Subject: [PATCH 03/15] Keep track of zone appearances on thread stacks Start keeping track, using the previously-introduced SrcLocCountMap, of the number of appearances of each zone on each thread's stack at a given time. --- server/TracyWorker.cpp | 21 +++++++++++++++------ server/TracyWorker.hpp | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 1b860248..bdaf24d4 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -394,6 +394,7 @@ Worker::Worker( const char* name, const char* program, const std::vectorzoneIdStack.pop_back(); auto& stack = td->stack; auto zone = stack.back_and_pop(); + td->DecStackCount( zone->SrcLoc() ); zone->SetEnd( v.timestamp ); #ifndef TRACY_NO_STATISTICS @@ -1819,16 +1820,21 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) if( mem.second->reconstruct ) jobs.emplace_back( std::thread( [this, mem = mem.second] { ReconstructMemAllocPlot( *mem ); } ) ); } - std::function>&, uint16_t)> ProcessTimeline; - ProcessTimeline = [this, &ProcessTimeline] ( Vector>& _vec, uint16_t thread ) + std::function>&, uint16_t)> ProcessTimeline; + ProcessTimeline = [this, &ProcessTimeline] ( SrcLocCountMap& countMap, Vector>& _vec, uint16_t thread ) { if( m_shutdown.load( std::memory_order_relaxed ) ) return; assert( _vec.is_magic() ); auto& vec = *(Vector*)( &_vec ); for( auto& zone : vec ) { - if( zone.IsEndValid() ) ReconstructZoneStatistics( zone, thread ); - if( zone.HasChildren() ) ProcessTimeline( GetZoneChildrenMutable( zone.Child() ), thread ); + if( zone.IsEndValid() ) ReconstructZoneStatistics( countMap, zone, thread ); + if( zone.HasChildren() ) + { + IncSrcLocCount( countMap, zone.SrcLoc() ); + ProcessTimeline( countMap, GetZoneChildrenMutable( zone.Child() ), thread ); + DecSrcLocCount( countMap, zone.SrcLoc() ); + } } }; @@ -1838,8 +1844,9 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) if( m_shutdown.load( std::memory_order_relaxed ) ) return; if( !t->timeline.empty() ) { + SrcLocCountMap countMap; // Don't touch thread compression cache in a thread. - ProcessTimeline( t->timeline, m_data.localThreadCompress.DecompressMustRaw( t->id ) ); + ProcessTimeline( countMap, t->timeline, m_data.localThreadCompress.DecompressMustRaw( t->id ) ); } } } ) ); @@ -3582,6 +3589,7 @@ void Worker::NewZone( ZoneEvent* zone, uint64_t thread ) auto td = m_threadCtxData; if( !td ) td = m_threadCtxData = NoticeThread( thread ); td->count++; + td->IncStackCount( zone->SrcLoc() ); const auto ssz = td->stack.size(); if( ssz == 0 ) { @@ -4736,6 +4744,7 @@ void Worker::ProcessZoneEnd( const QueueZoneEnd& ev ) assert( !stack.empty() ); auto zone = stack.back_and_pop(); assert( zone->End() == -1 ); + const auto isReentry = td->DecStackCount( zone->SrcLoc() ); const auto refTime = m_refTimeThread + ev.time; m_refTimeThread = refTime; const auto timeEnd = TscTime( refTime - m_data.baseTime ); @@ -7042,7 +7051,7 @@ void Worker::ReadTimelineHaveSize( FileRead& f, GpuEvent* zone, int64_t& refTime } #ifndef TRACY_NO_STATISTICS -void Worker::ReconstructZoneStatistics( ZoneEvent& zone, uint16_t thread ) +void Worker::ReconstructZoneStatistics( SrcLocCountMap& countMap, ZoneEvent& zone, uint16_t thread ) { assert( zone.IsEndValid() ); auto timeSpan = zone.End() - zone.Start(); diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index 0994ca11..ec6b39c1 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -831,7 +831,7 @@ private: tracy_force_inline void ReadTimelineHaveSize( FileRead& f, GpuEvent* zone, int64_t& refTime, int64_t& refGpuTime, int32_t& childIdx, uint64_t sz ); #ifndef TRACY_NO_STATISTICS - tracy_force_inline void ReconstructZoneStatistics( ZoneEvent& zone, uint16_t thread ); + tracy_force_inline void ReconstructZoneStatistics( SrcLocCountMap& countMap, ZoneEvent& zone, uint16_t thread ); #else tracy_force_inline void CountZoneStatistics( ZoneEvent* zone ); #endif From 66053e37f7334a266537cd24b4d5aa6ec4e2374d Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 5 Jun 2021 11:28:16 -0700 Subject: [PATCH 04/15] Add non-reentrant stats to SourceLocationZones Extend SourceLocationZones with fields to track the count and time of non-reentrant zone events -- that is, zone events which were the only appearances (at the time) of those zones on their threads' stacks. --- server/TracyWorker.cpp | 15 +++++++++++++++ server/TracyWorker.hpp | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index bdaf24d4..431a1e24 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -4798,6 +4798,13 @@ void Worker::ProcessZoneEnd( const QueueZoneEnd& ev ) if( slz->selfMin > selfSpan ) slz->selfMin = selfSpan; if( slz->selfMax < selfSpan ) slz->selfMax = selfSpan; slz->selfTotal += selfSpan; + if ( !isReentry ) + { + slz->nonReentrantCount++; + if( slz->nonReentrantMin > timeSpan ) slz->nonReentrantMin = timeSpan; + if( slz->nonReentrantMax < timeSpan ) slz->nonReentrantMax = timeSpan; + slz->nonReentrantTotal += timeSpan; + } if( !td->childTimeStack.empty() ) { td->childTimeStack.back() += timeSpan; @@ -7068,6 +7075,14 @@ void Worker::ReconstructZoneStatistics( SrcLocCountMap& countMap, ZoneEvent& zon if( slz.max < timeSpan ) slz.max = timeSpan; slz.total += timeSpan; slz.sumSq += double( timeSpan ) * timeSpan; + const auto isReentry = HasSrcLocCount( countMap, zone.SrcLoc() ); + if ( !isReentry ) + { + slz.nonReentrantCount++; + if( slz.nonReentrantMin > timeSpan ) slz.nonReentrantMin = timeSpan; + if( slz.nonReentrantMax < timeSpan ) slz.nonReentrantMax = timeSpan; + slz.nonReentrantTotal += timeSpan; + } if( zone.HasChildren() ) { auto& children = GetZoneChildren( zone.Child() ); diff --git a/server/TracyWorker.hpp b/server/TracyWorker.hpp index ec6b39c1..478ea5d8 100644 --- a/server/TracyWorker.hpp +++ b/server/TracyWorker.hpp @@ -184,6 +184,10 @@ private: int64_t selfMin = std::numeric_limits::max(); int64_t selfMax = std::numeric_limits::min(); int64_t selfTotal = 0; + size_t nonReentrantCount = 0; + int64_t nonReentrantMin = std::numeric_limits::max(); + int64_t nonReentrantMax = std::numeric_limits::min(); + int64_t nonReentrantTotal = 0; }; struct CallstackFrameIdHash From 9366e58d12181804844ba6ac72a7d327446a9e8e Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 5 Jun 2021 11:41:21 -0700 Subject: [PATCH 05/15] Introduce "Non-reentrant time" radio button Add to the statistics view an option for "Non-reentrant time", which displays the count of and time spent in zone events which were the only appearances (at that time) of their zones on their threads' stacks. Besides the GUI changes, this involves: - Introducing a tri-state accumulation mode to replace the boolean "self time": now there's "Self time only", "Child time", and "Non-reentrant time". - Removing the separate "selfTotal" from SrcLocZonesSlim, making "total" represent whichever of the now three options is active, which in turn requires keeping track of the accumulation mode in StatisticsCache and invalidating that cache when the accumulation mode changes. --- server/TracyView.cpp | 142 ++++++++++++++++++++++++------------------- server/TracyView.hpp | 12 +++- 2 files changed, 90 insertions(+), 64 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 9c079234..6dc8f4b1 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -12269,9 +12269,26 @@ struct SrcLocZonesSlim int16_t srcloc; size_t numZones; int64_t total; - int64_t selfTotal; }; +void View::AccumulationModeRadioButtons() +{ + if ( ImGui::RadioButton( ICON_FA_CLOCK " Self time only", m_statAccumulationMode == AccumulationMode::SelfOnly )) + { + m_statAccumulationMode = AccumulationMode::SelfOnly; + } + ImGui::SameLine(); + if ( ImGui::RadioButton( ICON_FA_CLOCK " Child time", m_statAccumulationMode == AccumulationMode::AllChildren )) + { + m_statAccumulationMode = AccumulationMode::AllChildren; + } + ImGui::SameLine(); + if ( ImGui::RadioButton( ICON_FA_CLOCK " Non-reentrant time", m_statAccumulationMode == AccumulationMode::NonReentrantChildren )) + { + m_statAccumulationMode = AccumulationMode::NonReentrantChildren; + } +} + void View::DrawStatistics() { ImGui::SetNextWindowSize( ImVec2( 1400, 600 ), ImGuiCond_FirstUseEver ); @@ -12349,19 +12366,18 @@ void View::DrawStatistics() if( !filterActive ) { auto cit = m_statCache.find( it->first ); - if( cit != m_statCache.end() && cit->second.range == m_statRange && cit->second.sourceCount == it->second.zones.size() ) + if( cit != m_statCache.end() && cit->second.range == m_statRange && cit->second.accumulationMode == m_statAccumulationMode && cit->second.sourceCount == it->second.zones.size() ) { if( cit->second.count != 0 ) { slzcnt++; - srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cit->second.count, cit->second.total, cit->second.selfTotal } ); + srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cit->second.count, cit->second.total } ); } } else { size_t cnt = 0; int64_t total = 0; - int64_t selfTotal = 0; for( auto& v : it->second.zones ) { auto& z = *v.Zone(); @@ -12370,17 +12386,24 @@ void View::DrawStatistics() if( start >= min && end <= max ) { const auto zt = end - start; - total += zt; - if( m_statSelf ) selfTotal += zt - GetZoneChildTimeFast( z ); - cnt++; + if ( m_statAccumulationMode == AccumulationMode::SelfOnly) + { + total += zt - GetZoneChildTimeFast( z ); + cnt++; + } + else if ( m_statAccumulationMode == AccumulationMode::AllChildren || !IsZoneReentry(z) ) + { + total += zt; + cnt++; + } } } if( cnt != 0 ) { slzcnt++; - srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cnt, total, selfTotal } ); + srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cnt, total } ); } - m_statCache[it->first] = StatisticsCache { RangeSlim { m_statRange.min, m_statRange.max, m_statRange.active }, it->second.zones.size(), cnt, total, selfTotal }; + m_statCache[it->first] = StatisticsCache { RangeSlim { m_statRange.min, m_statRange.max, m_statRange.active }, m_statAccumulationMode, it->second.zones.size(), cnt, total }; } } else @@ -12391,18 +12414,17 @@ void View::DrawStatistics() if( m_statisticsFilter.PassFilter( name ) ) { auto cit = m_statCache.find( it->first ); - if( cit != m_statCache.end() && cit->second.range == m_statRange && cit->second.sourceCount == it->second.zones.size() ) + if( cit != m_statCache.end() && cit->second.range == m_statRange && cit->second.accumulationMode == m_statAccumulationMode && cit->second.sourceCount == it->second.zones.size() ) { if( cit->second.count != 0 ) { - srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cit->second.count, cit->second.total, cit->second.selfTotal } ); + srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cit->second.count, cit->second.total } ); } } else { size_t cnt = 0; int64_t total = 0; - int64_t selfTotal = 0; for( auto& v : it->second.zones ) { auto& z = *v.Zone(); @@ -12411,16 +12433,23 @@ void View::DrawStatistics() if( start >= min && end <= max ) { const auto zt = end - start; - total += zt; - if( m_statSelf ) selfTotal += zt - GetZoneChildTimeFast( z ); - cnt++; + if ( m_statAccumulationMode == AccumulationMode::SelfOnly) + { + total += zt - GetZoneChildTimeFast( z ); + cnt++; + } + else if ( m_statAccumulationMode == AccumulationMode::AllChildren || !IsZoneReentry(z) ) + { + total += zt; + cnt++; + } } } if( cnt != 0 ) { - srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cnt, total, selfTotal } ); + srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, cnt, total } ); } - m_statCache[it->first] = StatisticsCache { RangeSlim { m_statRange.min, m_statRange.max, m_statRange.active }, it->second.zones.size(), cnt, total, selfTotal }; + m_statCache[it->first] = StatisticsCache { RangeSlim { m_statRange.min, m_statRange.max, m_statRange.active }, m_statAccumulationMode, it->second.zones.size(), cnt, total }; } } } @@ -12434,9 +12463,26 @@ void View::DrawStatistics() if( it->second.total != 0 ) { slzcnt++; + size_t count; + int64_t total; + switch( m_statAccumulationMode ) + { + case AccumulationMode::SelfOnly: + count = it->second.zones.size(); + total = it->second.selfTotal; + break; + case AccumulationMode::AllChildren: + count = it->second.zones.size(); + total = it->second.total; + break; + case AccumulationMode::NonReentrantChildren: + count = it->second.nonReentrantCount; + total = it->second.nonReentrantTotal; + break; + } if( !filterActive ) { - srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, it->second.zones.size(), it->second.total, it->second.selfTotal } ); + srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, count, total } ); } else { @@ -12444,7 +12490,7 @@ void View::DrawStatistics() auto name = m_worker.GetString( sl.name.active ? sl.name : sl.function ); if( m_statisticsFilter.PassFilter( name ) ) { - srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, it->second.zones.size(), it->second.total, it->second.selfTotal } ); + srcloc.push_back_no_space_check( SrcLocZonesSlim { it->first, count, total } ); } } } @@ -12459,7 +12505,7 @@ void View::DrawStatistics() ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine(); - ImGui::Checkbox( ICON_FA_CLOCK " Self time", &m_statSelf ); + AccumulationModeRadioButtons(); } else { @@ -12469,7 +12515,7 @@ void View::DrawStatistics() { ImGui::PushItemFlag( ImGuiItemFlags_Disabled, true ); ImGui::PushStyleVar( ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f ); - m_statSelf = true; + m_statAccumulationMode = AccumulationMode::SelfOnly; bool val = true; ImGui::Checkbox( ICON_FA_CLOCK " Self time", &val ); ImGui::PopItemFlag(); @@ -12483,7 +12529,7 @@ void View::DrawStatistics() } else { - ImGui::Checkbox( ICON_FA_CLOCK " Self time", &m_statSelf ); + AccumulationModeRadioButtons(); } ImGui::SameLine(); ImGui::Checkbox( ICON_FA_EYE_SLASH " Hide unknown", &m_statHideUnknown ); @@ -12614,27 +12660,13 @@ void View::DrawStatistics() } break; case 2: - if( m_statSelf ) + if( sortspec.SortDirection == ImGuiSortDirection_Ascending ) { - if( sortspec.SortDirection == ImGuiSortDirection_Ascending ) - { - pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.selfTotal < rhs.selfTotal; } ); - } - else - { - pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.selfTotal > rhs.selfTotal; } ); - } + pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total < rhs.total; } ); } else { - if( sortspec.SortDirection == ImGuiSortDirection_Ascending ) - { - pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total < rhs.total; } ); - } - else - { - pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total > rhs.total; } ); - } + pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total > rhs.total; } ); } break; case 3: @@ -12648,27 +12680,13 @@ void View::DrawStatistics() } break; case 4: - if( m_statSelf ) + if( sortspec.SortDirection == ImGuiSortDirection_Ascending ) { - if( sortspec.SortDirection == ImGuiSortDirection_Ascending ) - { - pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.selfTotal / lhs.numZones < rhs.selfTotal / rhs.numZones; } ); - } - else - { - pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.selfTotal / lhs.numZones > rhs.selfTotal / rhs.numZones; } ); - } + pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total / lhs.numZones < rhs.total / rhs.numZones; } ); } else { - if( sortspec.SortDirection == ImGuiSortDirection_Ascending ) - { - pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total / lhs.numZones < rhs.total / rhs.numZones; } ); - } - else - { - pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total / lhs.numZones > rhs.total / rhs.numZones; } ); - } + pdqsort_branchless( srcloc.begin(), srcloc.end(), []( const auto& lhs, const auto& rhs ) { return lhs.total / lhs.numZones > rhs.total / rhs.numZones; } ); } break; default: @@ -12721,7 +12739,7 @@ void View::DrawStatistics() ImGui::Unindent( indentVal ); } ImGui::TableNextColumn(); - const auto time = m_statSelf ? v.selfTotal : v.total; + const auto time = v.total; ImGui::TextUnformatted( TimeToString( time ) ); ImGui::SameLine(); char buf[64]; @@ -12730,7 +12748,7 @@ void View::DrawStatistics() ImGui::TableNextColumn(); ImGui::TextUnformatted( RealToString( v.numZones ) ); ImGui::TableNextColumn(); - ImGui::TextUnformatted( TimeToString( ( m_statSelf ? v.selfTotal : v.total ) / v.numZones ) ); + ImGui::TextUnformatted( TimeToString( time / v.numZones ) ); ImGui::PopID(); } ImGui::EndTable(); @@ -12971,7 +12989,7 @@ void View::DrawStatistics() } else { - if( m_statSelf ) + if( m_statAccumulationMode == AccumulationMode::SelfOnly ) { pdqsort_branchless( data.begin(), data.end(), []( const auto& l, const auto& r ) { return l.excl != r.excl ? l.excl > r.excl : l.symAddr < r.symAddr; } ); } @@ -13008,7 +13026,7 @@ void View::DrawStatistics() int idx = 0; for( auto& v : data ) { - const auto cnt = m_statSelf ? v.excl : v.incl; + const auto cnt = m_statAccumulationMode == AccumulationMode::SelfOnly ? v.excl : v.incl; if( cnt > 0 || showAll ) { const char* name = "[unknown]"; @@ -13247,7 +13265,7 @@ void View::DrawStatistics() inSymList.push_back( SymList { v.symAddr, statIt->second.incl, statIt->second.excl } ); } - if( m_statSelf ) + if( m_statAccumulationMode == AccumulationMode::SelfOnly ) { pdqsort_branchless( inSymList.begin(), inSymList.end(), []( const auto& l, const auto& r ) { return l.excl != r.excl ? l.excl > r.excl : l.symAddr < r.symAddr; } ); } @@ -13261,7 +13279,7 @@ void View::DrawStatistics() { ImGui::TableNextRow(); ImGui::TableNextColumn(); - const auto cnt = m_statSelf ? iv.excl : iv.incl; + const auto cnt = m_statAccumulationMode == AccumulationMode::SelfOnly ? iv.excl : iv.incl; if( cnt > 0 || showAll ) { auto sit = symMap.find( iv.symAddr ); diff --git a/server/TracyView.hpp b/server/TracyView.hpp index 66eb97a3..d14042fd 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -56,13 +56,20 @@ class View uint64_t count; }; + enum class AccumulationMode + { + SelfOnly, + AllChildren, + NonReentrantChildren + }; + struct StatisticsCache { RangeSlim range; + AccumulationMode accumulationMode; size_t sourceCount; size_t count; int64_t total; - int64_t selfTotal; }; public: @@ -187,6 +194,7 @@ private: void DrawMessages(); void DrawMessageLine( const MessageData& msg, bool hasCallstack, int& idx ); void DrawFindZone(); + void AccumulationModeRadioButtons(); void DrawStatistics(); void DrawMemory(); void DrawAllocList(); @@ -394,7 +402,7 @@ private: bool m_showCpuDataWindow = false; bool m_showAnnotationList = false; - bool m_statSelf = true; + AccumulationMode m_statAccumulationMode = AccumulationMode::SelfOnly; bool m_statSampleTime = true; int m_statMode = 0; int m_statSampleLocation = 2; From 894c90f867e1c6c691a7326ff13e2bb75eea5c44 Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 5 Jun 2021 11:41:56 -0700 Subject: [PATCH 06/15] Update manual with new non-reentrant-time option --- manual/tracy.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manual/tracy.tex b/manual/tracy.tex index 9e9a8801..c72dc285 100644 --- a/manual/tracy.tex +++ b/manual/tracy.tex @@ -2820,7 +2820,7 @@ If the trace capture was performed with call stack sampling enabled (as describe Here you will find a multi-column display of captured zones, which contains: the zone \emph{name} and \emph{location}, \emph{total time} spent in the zone, the \emph{count} of zone executions and the \emph{mean time spent in the zone per call}. The view may be sorted according to the three displayed values. -The \emph{\faClock{}~Self time} option determines how the displayed time is calculated. If it is disabled, the measurements will be inclusive, that is, containing execution time of zone's children. Enabling the option switches the measurement to exclusive, displaying just the time spent in zone, subtracting the child calls. +The \emph{\faClock{}~Child time} button displays inclusive measurements, that is, containing execution time of zone's children. The \emph{\faClock{}~Self time only} button switches the measurement to exclusive, displaying just the time spent in zone, subtracting the child calls. The \emph{\faClock{}~Non-reentrant time} button displays inclusive time, but counting only the first appearance of a given zone on a thread's stack. Clicking the \LMB{} left mouse button on a zone will open the individual zone statistics view in the find zone window (section~\ref{findzone}). @@ -2847,7 +2847,7 @@ The \emph{Time} or \emph{Count} column (depending on the \emph{\faStopwatch{}~Sh The last column, \emph{Code size}, displays the size of symbol in the executable image of the program. Since inlined routines are directly embedded into other functions, their symbol size will be based on the parent symbol, and displayed as 'less than'. In some cases this data won't be available. If the symbol code has been retrieved\footnote{Symbols larger than 64~KB are not captured.}, symbol size will be prepend with the \texttt{\faDatabase}~icon, and clicking the \RMB{}~right mouse button on the location column entry will open symbol view window (section~\ref{symbolview}). -Finally, the list can be filtered using the \emph{\faFilter{}~Filter symbols} entry field, just like in the instrumentation mode case. Additionally, you can also filter results by the originating image name of the symbol. Display of kernel symbols may be disabled with the \emph{\faHatWizard{}~Include kernel} switch. The exclusive/inclusive time counting mode can be switched using the \emph{\faClock{}~Self time} switch. Limiting the time range is also available, but is restricted to self time. If the \emph{\faPuzzlePiece{}~Show all} option is selected, the list will include not only call stack samples, but also all other symbols collected during the profiling process (this is enabled by default, if no sampling was performed). +Finally, the list can be filtered using the \emph{\faFilter{}~Filter symbols} entry field, just like in the instrumentation mode case. Additionally, you can also filter results by the originating image name of the symbol. Display of kernel symbols may be disabled with the \emph{\faHatWizard{}~Include kernel} switch. The exclusive/inclusive/non-reentrant time counting mode can be switched using the \emph{\faClock{}~Self time only}, \emph{\faClock{}~Child time} , and \emph{\faClock{}~Non-reentrant time} buttons. Limiting the time range is also available, but is restricted to self time. If the \emph{\faPuzzlePiece{}~Show all} option is selected, the list will include not only call stack samples, but also all other symbols collected during the profiling process (this is enabled by default, if no sampling was performed). \subsection{Find zone window} \label{findzone} From 913463635a2a275f7ec6bf27e5be8850dd916b88 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Wed, 23 Jun 2021 20:37:14 +0200 Subject: [PATCH 07/15] Cosmetics. --- server/TracyEvent.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/server/TracyEvent.hpp b/server/TracyEvent.hpp index 1f349a06..cae2c83f 100644 --- a/server/TracyEvent.hpp +++ b/server/TracyEvent.hpp @@ -589,7 +589,7 @@ enum { GhostZoneSize = sizeof( GhostZone ) }; using SrcLocCountMap = unordered_flat_map; -tracy_force_inline void IncSrcLocCount(SrcLocCountMap& countMap, int16_t srcloc) +static tracy_force_inline void IncSrcLocCount( SrcLocCountMap& countMap, int16_t srcloc ) { const auto it = countMap.find( srcloc ); if( it == countMap.end() ) @@ -602,7 +602,7 @@ tracy_force_inline void IncSrcLocCount(SrcLocCountMap& countMap, int16_t srcloc) it->second++; } -tracy_force_inline bool DecSrcLocCount(SrcLocCountMap& countMap, int16_t srcloc) +static tracy_force_inline bool DecSrcLocCount( SrcLocCountMap& countMap, int16_t srcloc ) { const auto it = countMap.find( srcloc ); assert( it != countMap.end() ); @@ -618,7 +618,7 @@ tracy_force_inline bool DecSrcLocCount(SrcLocCountMap& countMap, int16_t srcloc) return true; } -tracy_force_inline bool HasSrcLocCount(SrcLocCountMap& countMap, int16_t srcloc) +static tracy_force_inline bool HasSrcLocCount( const SrcLocCountMap& countMap, int16_t srcloc ) { const auto it = countMap.find( srcloc ); @@ -650,9 +650,8 @@ struct ThreadData SampleData pendingSample; uint64_t kernelSampleCnt; - tracy_force_inline void IncStackCount(int16_t srcloc) { IncSrcLocCount( stackCount, srcloc ); } - - tracy_force_inline bool DecStackCount(int16_t srcloc) { return DecSrcLocCount( stackCount, srcloc ); } + tracy_force_inline void IncStackCount( int16_t srcloc ) { IncSrcLocCount( stackCount, srcloc ); } + tracy_force_inline bool DecStackCount( int16_t srcloc ) { return DecSrcLocCount( stackCount, srcloc ); } }; struct GpuCtxThreadData From 9a22b8e83cdf74714537267ab2ee783342ed4ba2 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Wed, 23 Jun 2021 20:43:46 +0200 Subject: [PATCH 08/15] Cosmetics. --- server/TracyWorker.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index 431a1e24..02024b76 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -389,8 +389,7 @@ Worker::Worker( const char* name, const char* program, const std::vectorzoneIdStack.empty()) - continue; + if( td->zoneIdStack.empty() ) continue; td->zoneIdStack.pop_back(); auto& stack = td->stack; auto zone = stack.back_and_pop(); @@ -565,8 +564,7 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks ) char tmp[1024]; f.Read( tmp, sz ); m_captureName = std::string( tmp, tmp+sz ); - if (m_captureName.empty()) - m_captureName = f.GetFilename(); + if( m_captureName.empty() ) m_captureName = f.GetFilename(); } { f.Read( sz ); @@ -4798,7 +4796,7 @@ void Worker::ProcessZoneEnd( const QueueZoneEnd& ev ) if( slz->selfMin > selfSpan ) slz->selfMin = selfSpan; if( slz->selfMax < selfSpan ) slz->selfMax = selfSpan; slz->selfTotal += selfSpan; - if ( !isReentry ) + if( !isReentry ) { slz->nonReentrantCount++; if( slz->nonReentrantMin > timeSpan ) slz->nonReentrantMin = timeSpan; @@ -7076,7 +7074,7 @@ void Worker::ReconstructZoneStatistics( SrcLocCountMap& countMap, ZoneEvent& zon slz.total += timeSpan; slz.sumSq += double( timeSpan ) * timeSpan; const auto isReentry = HasSrcLocCount( countMap, zone.SrcLoc() ); - if ( !isReentry ) + if( !isReentry ) { slz.nonReentrantCount++; if( slz.nonReentrantMin > timeSpan ) slz.nonReentrantMin = timeSpan; From b392671a7ac22bd7578145410ee2916afc1c5109 Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Fri, 25 Jun 2021 21:27:45 -0700 Subject: [PATCH 09/15] Make time accumulation mode use combo box --- server/TracyView.cpp | 40 ++++++++++++++++++++++++++++------------ server/TracyView.hpp | 2 +- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 6dc8f4b1..2c124f6b 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -12271,21 +12271,37 @@ struct SrcLocZonesSlim int64_t total; }; -void View::AccumulationModeRadioButtons() +void View::AccumulationModeComboBox() { - if ( ImGui::RadioButton( ICON_FA_CLOCK " Self time only", m_statAccumulationMode == AccumulationMode::SelfOnly )) + ImGui::TextUnformatted( "Accumulation mode" ); + ImGui::SameLine(); + const char* accumulationModeTable = "Self only\0Including children\0Non-reentrant\0"; + ImGui::SetNextItemWidth( ImGui::CalcTextSize( "Including children" ).x + ImGui::GetTextLineHeight() * 2 ); + int accumulationMode; + switch ( m_statAccumulationMode ) { + case AccumulationMode::SelfOnly: + accumulationMode = 0; + break; + case AccumulationMode::AllChildren: + accumulationMode = 1; + break; + case AccumulationMode::NonReentrantChildren: + accumulationMode = 2; + break; + } + ImGui::Combo( "##accumulationMode", &accumulationMode, accumulationModeTable ); + switch ( accumulationMode ) + { + case 0: m_statAccumulationMode = AccumulationMode::SelfOnly; - } - ImGui::SameLine(); - if ( ImGui::RadioButton( ICON_FA_CLOCK " Child time", m_statAccumulationMode == AccumulationMode::AllChildren )) - { + break; + case 1: m_statAccumulationMode = AccumulationMode::AllChildren; - } - ImGui::SameLine(); - if ( ImGui::RadioButton( ICON_FA_CLOCK " Non-reentrant time", m_statAccumulationMode == AccumulationMode::NonReentrantChildren )) - { + break; + case 2: m_statAccumulationMode = AccumulationMode::NonReentrantChildren; + break; } } @@ -12505,7 +12521,7 @@ void View::DrawStatistics() ImGui::SameLine(); ImGui::Spacing(); ImGui::SameLine(); - AccumulationModeRadioButtons(); + AccumulationModeComboBox(); } else { @@ -12529,7 +12545,7 @@ void View::DrawStatistics() } else { - AccumulationModeRadioButtons(); + AccumulationModeComboBox(); } ImGui::SameLine(); ImGui::Checkbox( ICON_FA_EYE_SLASH " Hide unknown", &m_statHideUnknown ); diff --git a/server/TracyView.hpp b/server/TracyView.hpp index d14042fd..09a2139d 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -194,7 +194,7 @@ private: void DrawMessages(); void DrawMessageLine( const MessageData& msg, bool hasCallstack, int& idx ); void DrawFindZone(); - void AccumulationModeRadioButtons(); + void AccumulationModeComboBox(); void DrawStatistics(); void DrawMemory(); void DrawAllocList(); From d6761c2ffa107b24dcf631a2e88bff43652717de Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Fri, 25 Jun 2021 21:33:12 -0700 Subject: [PATCH 10/15] Update manual for accumulation mode combo box --- manual/tracy.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manual/tracy.tex b/manual/tracy.tex index c72dc285..a40d8593 100644 --- a/manual/tracy.tex +++ b/manual/tracy.tex @@ -2820,7 +2820,7 @@ If the trace capture was performed with call stack sampling enabled (as describe Here you will find a multi-column display of captured zones, which contains: the zone \emph{name} and \emph{location}, \emph{total time} spent in the zone, the \emph{count} of zone executions and the \emph{mean time spent in the zone per call}. The view may be sorted according to the three displayed values. -The \emph{\faClock{}~Child time} button displays inclusive measurements, that is, containing execution time of zone's children. The \emph{\faClock{}~Self time only} button switches the measurement to exclusive, displaying just the time spent in zone, subtracting the child calls. The \emph{\faClock{}~Non-reentrant time} button displays inclusive time, but counting only the first appearance of a given zone on a thread's stack. +In the \emph{~Accumulation mode} menu, the \emph{~Including children} selection selection displays inclusive measurements, that is, containing execution time of zone's children. The \emph{~Self only} selection switches the measurement to exclusive, displaying just the time spent in zone, subtracting the child calls. The \emph{~Non-reentrant} selection displays inclusive time, but counting only the first appearance of a given zone on a thread's stack. Clicking the \LMB{} left mouse button on a zone will open the individual zone statistics view in the find zone window (section~\ref{findzone}). @@ -2847,7 +2847,7 @@ The \emph{Time} or \emph{Count} column (depending on the \emph{\faStopwatch{}~Sh The last column, \emph{Code size}, displays the size of symbol in the executable image of the program. Since inlined routines are directly embedded into other functions, their symbol size will be based on the parent symbol, and displayed as 'less than'. In some cases this data won't be available. If the symbol code has been retrieved\footnote{Symbols larger than 64~KB are not captured.}, symbol size will be prepend with the \texttt{\faDatabase}~icon, and clicking the \RMB{}~right mouse button on the location column entry will open symbol view window (section~\ref{symbolview}). -Finally, the list can be filtered using the \emph{\faFilter{}~Filter symbols} entry field, just like in the instrumentation mode case. Additionally, you can also filter results by the originating image name of the symbol. Display of kernel symbols may be disabled with the \emph{\faHatWizard{}~Include kernel} switch. The exclusive/inclusive/non-reentrant time counting mode can be switched using the \emph{\faClock{}~Self time only}, \emph{\faClock{}~Child time} , and \emph{\faClock{}~Non-reentrant time} buttons. Limiting the time range is also available, but is restricted to self time. If the \emph{\faPuzzlePiece{}~Show all} option is selected, the list will include not only call stack samples, but also all other symbols collected during the profiling process (this is enabled by default, if no sampling was performed). +Finally, the list can be filtered using the \emph{\faFilter{}~Filter symbols} entry field, just like in the instrumentation mode case. Additionally, you can also filter results by the originating image name of the symbol. Display of kernel symbols may be disabled with the \emph{\faHatWizard{}~Include kernel} switch. The exclusive/inclusive/non-reentrant time counting mode can be switched using the \emph{~Accumulation mode} menu. Limiting the time range is also available, but is restricted to self time. If the \emph{\faPuzzlePiece{}~Show all} option is selected, the list will include not only call stack samples, but also all other symbols collected during the profiling process (this is enabled by default, if no sampling was performed). \subsection{Find zone window} \label{findzone} From f000dce73f0a66c773178df76dc96578c255898d Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 26 Jun 2021 08:30:15 -0700 Subject: [PATCH 11/15] Replace "enum class" switches with explicit casts --- server/TracyView.cpp | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 2c124f6b..858b9ac0 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -12277,32 +12277,9 @@ void View::AccumulationModeComboBox() ImGui::SameLine(); const char* accumulationModeTable = "Self only\0Including children\0Non-reentrant\0"; ImGui::SetNextItemWidth( ImGui::CalcTextSize( "Including children" ).x + ImGui::GetTextLineHeight() * 2 ); - int accumulationMode; - switch ( m_statAccumulationMode ) - { - case AccumulationMode::SelfOnly: - accumulationMode = 0; - break; - case AccumulationMode::AllChildren: - accumulationMode = 1; - break; - case AccumulationMode::NonReentrantChildren: - accumulationMode = 2; - break; - } + int accumulationMode = static_cast( m_statAccumulationMode ); ImGui::Combo( "##accumulationMode", &accumulationMode, accumulationModeTable ); - switch ( accumulationMode ) - { - case 0: - m_statAccumulationMode = AccumulationMode::SelfOnly; - break; - case 1: - m_statAccumulationMode = AccumulationMode::AllChildren; - break; - case 2: - m_statAccumulationMode = AccumulationMode::NonReentrantChildren; - break; - } + m_statAccumulationMode = static_cast( accumulationMode ); } void View::DrawStatistics() From 1dd117533e848ebb19e54fa038f1cbe8c776205f Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 26 Jun 2021 10:36:46 -0700 Subject: [PATCH 12/15] Avoid non-reentrant option in sampling/symbol view --- server/TracyView.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 858b9ac0..8950de86 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -12275,8 +12275,12 @@ void View::AccumulationModeComboBox() { ImGui::TextUnformatted( "Accumulation mode" ); ImGui::SameLine(); - const char* accumulationModeTable = "Self only\0Including children\0Non-reentrant\0"; + const char* accumulationModeTable = m_statMode == 0 ? "Self only\0Including children\0Non-reentrant\0" : "Self only\0Including children\0"; ImGui::SetNextItemWidth( ImGui::CalcTextSize( "Including children" ).x + ImGui::GetTextLineHeight() * 2 ); + if ( m_statMode != 0 && m_statAccumulationMode == AccumulationMode::NonReentrantChildren ) + { + m_statAccumulationMode = AccumulationMode::SelfOnly; + } int accumulationMode = static_cast( m_statAccumulationMode ); ImGui::Combo( "##accumulationMode", &accumulationMode, accumulationModeTable ); m_statAccumulationMode = static_cast( accumulationMode ); From e105d2d96c99baacb660f1aa0f042d8fe3364870 Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 26 Jun 2021 10:40:28 -0700 Subject: [PATCH 13/15] Aesthetic fixes to accumulation mode combo box Shorter text fields and more spacing. --- server/TracyView.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 8950de86..1c900ca4 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -12273,10 +12273,13 @@ struct SrcLocZonesSlim void View::AccumulationModeComboBox() { - ImGui::TextUnformatted( "Accumulation mode" ); ImGui::SameLine(); - const char* accumulationModeTable = m_statMode == 0 ? "Self only\0Including children\0Non-reentrant\0" : "Self only\0Including children\0"; - ImGui::SetNextItemWidth( ImGui::CalcTextSize( "Including children" ).x + ImGui::GetTextLineHeight() * 2 ); + ImGui::Spacing(); + ImGui::SameLine(); + ImGui::TextUnformatted( "Timing" ); + ImGui::SameLine(); + const char* accumulationModeTable = m_statMode == 0 ? "Self only\0With children\0Non-reentrant\0" : "Self only\0With children\0"; + ImGui::SetNextItemWidth( ImGui::CalcTextSize( "Non-reentrant" ).x + ImGui::GetTextLineHeight() * 2 ); if ( m_statMode != 0 && m_statAccumulationMode == AccumulationMode::NonReentrantChildren ) { m_statAccumulationMode = AccumulationMode::SelfOnly; @@ -12284,6 +12287,9 @@ void View::AccumulationModeComboBox() int accumulationMode = static_cast( m_statAccumulationMode ); ImGui::Combo( "##accumulationMode", &accumulationMode, accumulationModeTable ); m_statAccumulationMode = static_cast( accumulationMode ); + ImGui::SameLine(); + ImGui::Spacing(); + ImGui::SameLine(); } void View::DrawStatistics() @@ -12499,9 +12505,6 @@ void View::DrawStatistics() ImGui::Spacing(); ImGui::SameLine(); TextFocused( "Visible zones:", RealToString( srcloc.size() ) ); - ImGui::SameLine(); - ImGui::Spacing(); - ImGui::SameLine(); AccumulationModeComboBox(); } else From d6fd252ce4f17a07778f536f67077bd56a7421b3 Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 26 Jun 2021 10:30:00 -0700 Subject: [PATCH 14/15] Add more spacing to pre-existing options --- server/TracyView.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 1c900ca4..954ad150 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -12322,10 +12322,14 @@ void View::DrawStatistics() if( hasSamples ) { + ImGui::Spacing(); + ImGui::SameLine(); ImGui::RadioButton( ICON_FA_EYE_DROPPER " Sampling", &m_statMode, 1 ); } else { + ImGui::Spacing(); + ImGui::SameLine(); ImGui::RadioButton( ICON_FA_PUZZLE_PIECE " Symbols", &m_statMode, 1 ); } ImGui::SameLine(); @@ -12532,14 +12536,24 @@ void View::DrawStatistics() AccumulationModeComboBox(); } ImGui::SameLine(); + ImGui::Spacing(); + ImGui::SameLine(); ImGui::Checkbox( ICON_FA_EYE_SLASH " Hide unknown", &m_statHideUnknown ); ImGui::SameLine(); + ImGui::Spacing(); + ImGui::SameLine(); ImGui::Checkbox( ICON_FA_PUZZLE_PIECE " Show all", &m_showAllSymbols ); ImGui::SameLine(); + ImGui::Spacing(); + ImGui::SameLine(); ImGui::Checkbox( ICON_FA_SITEMAP " Inlines", &m_statSeparateInlines ); ImGui::SameLine(); + ImGui::Spacing(); + ImGui::SameLine(); ImGui::Checkbox( ICON_FA_AT " Address", &m_statShowAddress ); ImGui::SameLine(); + ImGui::Spacing(); + ImGui::SameLine(); ImGui::TextUnformatted( "Location:" ); ImGui::SameLine(); const char* locationTable = "Entry\0Sample\0Smart\0"; From 68ec7abdf4bc9ea48c70f73a53805906f78a47fc Mon Sep 17 00:00:00 2001 From: Terence Rokop Date: Sat, 26 Jun 2021 11:51:57 -0700 Subject: [PATCH 15/15] Move responsibility for spacing of combo box Thereby fix a spurious horizontal separator bar. --- server/TracyView.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 954ad150..7015e963 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -12273,9 +12273,6 @@ struct SrcLocZonesSlim void View::AccumulationModeComboBox() { - ImGui::SameLine(); - ImGui::Spacing(); - ImGui::SameLine(); ImGui::TextUnformatted( "Timing" ); ImGui::SameLine(); const char* accumulationModeTable = m_statMode == 0 ? "Self only\0With children\0Non-reentrant\0" : "Self only\0With children\0"; @@ -12287,9 +12284,6 @@ void View::AccumulationModeComboBox() int accumulationMode = static_cast( m_statAccumulationMode ); ImGui::Combo( "##accumulationMode", &accumulationMode, accumulationModeTable ); m_statAccumulationMode = static_cast( accumulationMode ); - ImGui::SameLine(); - ImGui::Spacing(); - ImGui::SameLine(); } void View::DrawStatistics() @@ -12509,6 +12503,9 @@ void View::DrawStatistics() ImGui::Spacing(); ImGui::SameLine(); TextFocused( "Visible zones:", RealToString( srcloc.size() ) ); + ImGui::SameLine(); + ImGui::Spacing(); + ImGui::SameLine(); AccumulationModeComboBox(); } else @@ -12533,6 +12530,9 @@ void View::DrawStatistics() } else { + ImGui::SameLine(); + ImGui::Spacing(); + ImGui::SameLine(); AccumulationModeComboBox(); } ImGui::SameLine();