diff --git a/server/TracyTimelineDraw.hpp b/server/TracyTimelineDraw.hpp index f73a3e85..24fd90e0 100644 --- a/server/TracyTimelineDraw.hpp +++ b/server/TracyTimelineDraw.hpp @@ -30,40 +30,25 @@ struct TimelineDraw enum class ContextSwitchDrawType : uint8_t { Waiting, - FoldedOne, - FoldedMulti, + Folded, Running }; -struct ContextSwitchDrawFolded -{ - Int48 rend; - int num; -}; - -struct ContextSwitchDrawWaiting -{ - short_ptr prev; - uint32_t waitStack; -}; - struct ContextSwitchDraw { ContextSwitchDrawType type; - short_ptr ev; - union - { - ContextSwitchDrawFolded folded; - ContextSwitchDrawWaiting waiting; - }; + uint32_t idx; + uint32_t data; // Folded: number of items -OR- Waiting: wait stack }; + struct SamplesDraw { uint32_t num; uint32_t idx; }; + struct MessagesDraw { short_ptr msg; diff --git a/server/TracyTimelineItemThread.cpp b/server/TracyTimelineItemThread.cpp index ce7235a8..ae03e333 100644 --- a/server/TracyTimelineItemThread.cpp +++ b/server/TracyTimelineItemThread.cpp @@ -469,7 +469,7 @@ void TimelineItemThread::PreprocessContextSwitches( const TimelineContext& ctx, if( it == citend ) return; if( citend != vec.end() ) ++citend; - const auto MinCtxNs = MinCtxSize * nspx; + const auto MinCtxNs = int64_t( round( GetScale() * MinCtxSize * nspx ) ); const auto& sampleData = m_thread->samples; auto pit = citend; @@ -492,50 +492,32 @@ void TimelineItemThread::PreprocessContextSwitches( const TimelineContext& ctx, } if( found ) waitStack = sdit->callstack.Val(); } - - auto& ref = m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Waiting, &ev } ); - ref.waiting.prev = pit; - ref.waiting.waitStack = waitStack; + m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Waiting, uint32_t( it - vec.begin() ), waitStack } ); } const auto end = ev.IsEndValid() ? ev.End() : m_worker.GetLastTime(); const auto zsz = end - ev.Start(); if( zsz < MinCtxNs ) { - int num = 0; - auto px1ns = end - vStart; - auto rend = end; auto nextTime = end + MinCtxNs; + auto next = it + 1; for(;;) { - const auto prevIt = it; - it = std::lower_bound( it, citend, nextTime, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } ); - if( it == prevIt ) ++it; - num += std::distance( prevIt, it ); - if( it == citend ) break; - const auto nend = it->IsEndValid() ? it->End() : m_worker.GetLastTime(); - const auto nsnext = nend - vStart; - if( nsnext - px1ns >= MinCtxNs * 2 ) break; - px1ns = nsnext; - rend = nend; - nextTime = nend + nspx; - } - if( num == 1 ) - { - auto& ref = m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::FoldedOne, &ev } ); - ref.folded.rend = rend; - } - else - { - auto& ref = m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::FoldedMulti, &ev } ); - ref.folded.rend = rend; - ref.folded.num = num; + next = std::lower_bound( next, citend, nextTime, [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } ); + if( next == citend ) break; + auto prev = next - 1; + const auto pt = prev->IsEndValid() ? prev->End() : m_worker.GetLastTime(); + const auto nt = next->IsEndValid() ? next->End() : m_worker.GetLastTime(); + if( nt - pt >= MinCtxNs ) break; + nextTime = nt + MinCtxNs; } + m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Folded, uint32_t( it - vec.begin() ), uint32_t( next - it ) } ); + it = next; pit = it-1; } else { - m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Running, &ev } ); + m_ctxDraw.emplace_back( ContextSwitchDraw { ContextSwitchDrawType::Running, uint32_t( it - vec.begin() ) } ); pit = it; ++it; } diff --git a/server/TracyView.hpp b/server/TracyView.hpp index e0acae7c..6249763c 100644 --- a/server/TracyView.hpp +++ b/server/TracyView.hpp @@ -212,7 +212,7 @@ private: void DrawTimeline(); void DrawSampleList( const TimelineContext& ctx, const std::vector& drawList, const Vector& vec, int offset ); void DrawZoneList( const TimelineContext& ctx, const std::vector& drawList, int offset, uint64_t tid ); - void DrawContextSwitchList( const TimelineContext& ctx, const std::vector& drawList, int offset, int endOffset, bool isFiber ); + void DrawContextSwitchList( const TimelineContext& ctx, const std::vector& drawList, const Vector& ctxSwitch, int offset, int endOffset, bool isFiber ); int DispatchGpuZoneLevel( const Vector>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift ); template int DrawGpuZoneLevel( const V& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, uint64_t thread, float yMin, float yMax, int64_t begin, int drift ); diff --git a/server/TracyView_ContextSwitch.cpp b/server/TracyView_ContextSwitch.cpp index 0cc36c3d..b43769ef 100644 --- a/server/TracyView_ContextSwitch.cpp +++ b/server/TracyView_ContextSwitch.cpp @@ -134,7 +134,7 @@ const char* View::DecodeContextSwitchState( uint8_t state ) } } -void View::DrawContextSwitchList( const TimelineContext& ctx, const std::vector& drawList, int offset, int endOffset, bool isFiber ) +void View::DrawContextSwitchList( const TimelineContext& ctx, const std::vector& drawList, const Vector& ctxSwitch, int offset, int endOffset, bool isFiber ) { constexpr float MinCtxSize = 4; @@ -154,12 +154,13 @@ void View::DrawContextSwitchList( const TimelineContext& ctx, const std::vector< for( auto& v : drawList ) { - const auto& ev = *v.ev; + const auto it = ctxSwitch.begin() + v.idx; + const auto& ev = *it; switch( v.type ) { case ContextSwitchDrawType::Waiting: { - const auto& prev = *v.waiting.prev; + const auto& prev = *(it-1); const bool migration = prev.Cpu() != ev.Cpu(); const auto px0 = std::max( { ( prev.End() - vStart ) * pxns, -10.0, double( minpx ) } ); const auto pxw = ( ev.WakeupVal() - vStart ) * pxns; @@ -238,7 +239,7 @@ void View::DrawContextSwitchList( const TimelineContext& ctx, const std::vector< } if( tooltip ) { - const auto waitStack = v.waiting.waitStack; + const auto waitStack = v.data; if( waitStack ) { ImGui::Separator(); @@ -254,58 +255,58 @@ void View::DrawContextSwitchList( const TimelineContext& ctx, const std::vector< } break; } - case ContextSwitchDrawType::FoldedOne: + case ContextSwitchDrawType::Folded: { + const auto num = v.data; const auto px0 = std::max( ( ev.Start() - vStart ) * pxns, -10.0 ); - const auto end = v.folded.rend.Val(); + const auto eit = it + num - 1; + const auto end = eit->IsEndValid() ? eit->End() : m_worker.GetLastTime(); const auto px1ns = end - vStart; minpx = std::min( std::max( px1ns * pxns, px0+MinCtxSize ), double( w + 10 ) ); - DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( minpx, offset + ty05 - 0.5f ), 0xFF22DD22, lineSize ); - if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) ) + if( num == 1 ) { - ImGui::BeginTooltip(); - if( isFiber ) + DrawLine( draw, dpos + ImVec2( px0, offset + ty05 - 0.5f ), dpos + ImVec2( minpx, offset + ty05 - 0.5f ), 0xFF22DD22, lineSize ); + if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) ) { - const auto tid = m_worker.DecompressThread( ev.Thread() ); - TextFocused( "Fiber is", "running" ); - TextFocused( "Activity time:", TimeToString( end - ev.Start() ) ); - TextFocused( "Thread:", m_worker.GetThreadName( tid ) ); - ImGui::SameLine(); - ImGui::TextDisabled( "(%s)", RealToString( tid ) ); - } - else - { - TextFocused( "Thread is", "running" ); - TextFocused( "Activity time:", TimeToString( end - ev.Start() ) ); - TextFocused( "CPU:", RealToString( ev.Cpu() ) ); - } - ImGui::EndTooltip(); + ImGui::BeginTooltip(); + if( isFiber ) + { + const auto tid = m_worker.DecompressThread( ev.Thread() ); + TextFocused( "Fiber is", "running" ); + TextFocused( "Activity time:", TimeToString( end - ev.Start() ) ); + TextFocused( "Thread:", m_worker.GetThreadName( tid ) ); + ImGui::SameLine(); + ImGui::TextDisabled( "(%s)", RealToString( tid ) ); + } + else + { + TextFocused( "Thread is", "running" ); + TextFocused( "Activity time:", TimeToString( end - ev.Start() ) ); + TextFocused( "CPU:", RealToString( ev.Cpu() ) ); + } + ImGui::EndTooltip(); - if( IsMouseClicked( 2 ) ) - { - ZoomToRange( ev.Start(), end ); + if( IsMouseClicked( 2 ) ) + { + ZoomToRange( ev.Start(), end ); + } } } - break; - } - case ContextSwitchDrawType::FoldedMulti: - { - const auto px0 = std::max( ( ev.Start() - vStart ) * pxns, -10.0 ); - const auto end = v.folded.rend.Val(); - const auto px1ns = end - vStart; - minpx = std::min( std::max( px1ns * pxns, px0+MinCtxSize ), double( w + 10 ) ); - DrawZigZag( draw, wpos + ImVec2( 0, offset + ty05 ), px0, minpx, ty/4, 0xFF888888, 1.5 ); - if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) ) + else { - ImGui::BeginTooltip(); - TextFocused( isFiber ? "Fiber is" : "Thread is", "changing activity multiple times" ); - TextFocused( "Number of running regions:", RealToString( v.folded.num ) ); - TextFocused( "Time:", TimeToString( end - ev.Start() ) ); - ImGui::EndTooltip(); - - if( IsMouseClicked( 2 ) ) + DrawZigZag( draw, wpos + ImVec2( 0, offset + ty05 ), px0, minpx, ty/4, 0xFF888888, 1.5 ); + if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty + 1 ) ) ) { - ZoomToRange( ev.Start(), end ); + ImGui::BeginTooltip(); + TextFocused( isFiber ? "Fiber is" : "Thread is", "changing activity multiple times" ); + TextFocused( "Number of running regions:", RealToString( num ) ); + TextFocused( "Time:", TimeToString( end - ev.Start() ) ); + ImGui::EndTooltip(); + + if( IsMouseClicked( 2 ) ) + { + ZoomToRange( ev.Start(), end ); + } } } break; diff --git a/server/TracyView_ZoneTimeline.cpp b/server/TracyView_ZoneTimeline.cpp index a563a33a..ccf209f3 100644 --- a/server/TracyView_ZoneTimeline.cpp +++ b/server/TracyView_ZoneTimeline.cpp @@ -69,7 +69,9 @@ void View::DrawThread( const TimelineContext& ctx, const ThreadData& thread, con if( hasCtxSwitch ) { - DrawContextSwitchList( ctx, ctxDraw, ctxOffset, offset, thread.isFiber ); + auto ctxSwitch = m_worker.GetContextSwitchData( thread.id ); + assert( ctxSwitch ); + DrawContextSwitchList( ctx, ctxDraw, ctxSwitch->v, ctxOffset, offset, thread.isFiber ); } if( hasSamples ) {