From 2d5e397c9f9a079723fe4e822b3eb31b19e89b2f Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sat, 25 Jul 2026 22:13:25 +0200 Subject: [PATCH] Exclude context switch samples from the sampling flame graph. Context switch samples are excluded from the sampling statistics, but the flame graph built from thread samples included them. Threads which spend time blocked accumulated large scheduler towers which none of the other sampling views show, and the flame graph totals did not correspond to the statistics for the same trace. Filter the samples the same way the trace load jobs do. --- profiler/src/profiler/TracyView.hpp | 2 +- profiler/src/profiler/TracyView_FlameGraph.cpp | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/profiler/src/profiler/TracyView.hpp b/profiler/src/profiler/TracyView.hpp index a9a19e7d..7391d246 100644 --- a/profiler/src/profiler/TracyView.hpp +++ b/profiler/src/profiler/TracyView.hpp @@ -360,7 +360,7 @@ private: void DrawFlameGraphItem( const FlameGraphItem& item, FlameGraphContext& ctx, int depth, bool samples ); void BuildFlameGraph( const Worker& worker, std::vector& data, const Vector>& zones ); void BuildFlameGraph( const Worker& worker, std::vector& data, const Vector>& zones, const ContextSwitch* ctx ); - void BuildFlameGraph( const Worker& worker, std::vector& data, const Vector& samples, unordered_flat_map& externalCache, uint32_t& lastImage, uint32_t& lastSource ); + void BuildFlameGraph( const Worker& worker, std::vector& data, const Vector& samples, const SortedVector& ctxSamples, unordered_flat_map& externalCache, uint32_t& lastImage, uint32_t& lastSource ); void ListMemData( std::vector& vec, const std::function& DrawAddress, int64_t startTime = -1, uint64_t pool = 0 ); diff --git a/profiler/src/profiler/TracyView_FlameGraph.cpp b/profiler/src/profiler/TracyView_FlameGraph.cpp index 50153caf..3c4b7736 100644 --- a/profiler/src/profiler/TracyView_FlameGraph.cpp +++ b/profiler/src/profiler/TracyView_FlameGraph.cpp @@ -243,7 +243,7 @@ void View::BuildFlameGraph( const Worker& worker, std::vector& d } } -void View::BuildFlameGraph( const Worker& worker, std::vector& data, const Vector& samples, unordered_flat_map& externalCache, uint32_t& lastImage, uint32_t& lastSource ) +void View::BuildFlameGraph( const Worker& worker, std::vector& data, const Vector& samples, const SortedVector& ctxSamples, unordered_flat_map& externalCache, uint32_t& lastImage, uint32_t& lastSource ) { struct FrameCache { @@ -254,6 +254,7 @@ void View::BuildFlameGraph( const Worker& worker, std::vector& d std::vector cache; + const SampleData* cit = ctxSamples.begin(); for( auto& v : samples ) { if ( m_flameGraphInvariant.range.active ) @@ -265,6 +266,14 @@ void View::BuildFlameGraph( const Worker& worker, std::vector& d } } + // Context switch samples are excluded, following the sampling statistics. + if( cit != ctxSamples.end() ) + { + const auto vt = v.time.Val(); + cit = std::lower_bound( cit, ctxSamples.end(), vt, []( const auto& l, const auto& r ) { return (uint64_t)l.time.Val() < (uint64_t)r; } ); + if( cit != ctxSamples.end() && cit->time.Val() == vt ) continue; + } + cache.clear(); const auto cs = v.callstack.Val(); @@ -1149,7 +1158,7 @@ void View::DrawFlameGraph() unordered_flat_map externalCache; uint32_t lastImage = 0; uint32_t lastSource = 0; - BuildFlameGraph( m_worker, threadData[idx], thread->samples, externalCache, lastImage, lastSource ); + BuildFlameGraph( m_worker, threadData[idx], thread->samples, thread->ctxSwitchSamples, externalCache, lastImage, lastSource ); } ); idx++; }