diff options
author | Bartosz Taudul <wolf.pld@gmail.com> | 2019-08-13 16:10:44 +0300 |
---|---|---|
committer | Bartosz Taudul <wolf.pld@gmail.com> | 2019-08-13 17:20:43 +0300 |
commit | 71a5cffc137d3508c58907b2e491192de9b59e2d (patch) | |
tree | cf5a253fc98a67eb5647fb4c1f1132a633dc539e /server/TracyView.cpp | |
parent | f285e0f5cc063e60b5c889ca5082cbd65add0843 (diff) |
Add context switch tooltips.
Diffstat (limited to 'server/TracyView.cpp')
-rw-r--r-- | server/TracyView.cpp | 180 |
1 files changed, 177 insertions, 3 deletions
diff --git a/server/TracyView.cpp b/server/TracyView.cpp index 2141d6f6..758a959a 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -1888,7 +1888,7 @@ void View::DrawZones() auto ctxSwitch = m_worker.GetContextSwitchData( v->id ); if( ctxSwitch ) { - DrawContextSwitches( ctxSwitch, pxns, int64_t( nspx ), wpos, offset ); + DrawContextSwitches( ctxSwitch, hover, pxns, int64_t( nspx ), wpos, offset ); offset += round( ostep * 0.75f ); } } @@ -2200,7 +2200,108 @@ void View::DrawZones() } } -void View::DrawContextSwitches( const ContextSwitch* ctx, double pxns, int64_t nspx, const ImVec2& wpos, int offset ) +static const char* DecodeContextSwitchReasonCode( uint8_t reason ) +{ + switch( reason ) + { + case 0: return "Executive"; + case 1: return "FreePage"; + case 2: return "PageIn"; + case 3: return "PoolAllocation"; + case 4: return "DelayExecution"; + case 5: return "Suspended"; + case 6: return "UserRequest"; + case 7: return "WrExecutive"; + case 8: return "WrFreePage"; + case 9: return "WrPageIn"; + case 10: return "WrPoolAllocation"; + case 11: return "WrDelayExecution"; + case 12: return "WrSuspended"; + case 13: return "WrUserRequest"; + case 14: return "WrEventPair"; + case 15: return "WrQueue"; + case 16: return "WrLpcReceive"; + case 17: return "WrLpcReply"; + case 18: return "WrVirtualMemory"; + case 19: return "WrPageOut"; + case 20: return "WrRendezvous"; + case 21: return "WrKeyedEvent"; + case 22: return "WrTerminated"; + case 23: return "WrProcessInSwap"; + case 24: return "WrCpuRateControl"; + case 25: return "WrCalloutStack"; + case 26: return "WrKernel"; + case 27: return "WrResource"; + case 28: return "WrPushLock"; + case 29: return "WrMutex"; + case 30: return "WrQuantumEnd"; + case 31: return "WrDispatchInt"; + case 32: return "WrPreempted"; + case 33: return "WrYieldExecution"; + case 34: return "WrFastMutex"; + case 35: return "WrGuardedMutex"; + case 36: return "WrRundown"; + case 37: return "MaximumWaitReason"; + default: return "unknown"; + } +} + +static const char* DecodeContextSwitchReason( uint8_t reason ) +{ + switch( reason ) + { + case 0: return "(Thread is waiting for the scheduler)"; + case 1: return "(Thread is waiting for a free virtual memory page)"; + case 2: return "(Thread is waiting for a virtual memory page to arrive in memory)"; + case 4: return "(Thread execution is delayed)"; + case 5: return "(Thread execution is suspended)"; + case 6: return "(Thread is waiting on object - WaitForSingleObject, etc.)"; + case 7: return "(Thread is waiting for the scheduler)"; + case 8: return "(Thread is waiting for a free virtual memory page)"; + case 9: return "(Thread is waiting for a virtual memory page to arrive in memory)"; + case 11: return "(Thread execution is delayed)"; + case 12: return "(Thread execution is suspended)"; + case 13: return "(Thread is waiting for window messages)"; + case 15: return "(Thread is waiting on KQUEUE)"; + case 24: return "(CPU rate limiting)"; + case 34: return "(Waiting for a Fast Mutex)"; + default: return ""; + } +} + +static const char* DecodeContextSwitchStateCode( uint8_t state ) +{ + switch( state ) + { + case 0: return "Initialized"; + case 1: return "Ready"; + case 2: return "Running"; + case 3: return "Standby"; + case 4: return "Terminated"; + case 5: return "Waiting"; + case 6: return "Transition"; + case 7: return "DeferredReady"; + default: return "unknown"; + } +} + +static const char* DecodeContextSwitchState( uint8_t state ) +{ + switch( state ) + { + case 0: return "(Thread has been initialized, but has not yet started)"; + case 1: return "(Thread is waiting to use a processor because no processor is free. The thread is prepared to run on the next available processor)"; + case 2: return "(Thread is currently using a processor)"; + case 3: return "(Thread is about to use a processor)"; + case 4: return "(Thread has finished executing and has exited)"; + case 5: return "(Thread is not ready to use the processor because it is waiting for a peripheral operation to complete or a resource to become free)"; + case 6: return "(Thread is waiting for a resource, other than the processor, before it can execute)"; + case 7: return "(Thread has beed selected to run on a specific processor but have not yet beed scheduled)"; + default: return ""; + } +} + +void View::DrawContextSwitches( const ContextSwitch* ctx, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset ) { auto& vec = ctx->v; auto it = std::lower_bound( vec.begin(), vec.end(), std::max<int64_t>( 0, m_zvStart ), [] ( const auto& l, const auto& r ) { return (uint64_t)l.end < (uint64_t)r; } ); @@ -2223,10 +2324,44 @@ void View::DrawContextSwitches( const ContextSwitch* ctx, double pxns, int64_t n auto& ev = *it; if( pit != citend ) { + const bool migration = pit->cpu != ev.cpu; const auto px0 = std::max( { ( pit->end - m_zvStart ) * pxns, -10.0, minpx } ); const auto px1 = std::min( ( ev.start - m_zvStart ) * pxns, w + 10.0 ); - const auto color = pit->cpu != ev.cpu ? 0xFFEE7711 : 0xFF2222AA; + const auto color = migration ? 0xFFEE7711 : 0xFF2222AA; draw->AddLine( wpos + ImVec2( px0, round( offset + ty * 0.5 ) - 0.5 ), wpos + ImVec2( px1, round( offset + ty * 0.5 ) - 0.5 ), color, 2 ); + + if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + ty ) ) ) + { + ImGui::BeginTooltip(); + TextFocused( "Thread is", migration ? "migrating CPUs" : "waiting" ); + TextFocused( "Waiting time:", TimeToString( ev.start - pit->end ) ); + if( migration ) + { + TextFocused( "CPU:", RealToString( pit->cpu, true ) ); + ImGui::SameLine(); +#ifdef TRACY_EXTENDED_FONT + TextFocused( ICON_FA_LONG_ARROW_ALT_RIGHT, RealToString( ev.cpu, true ) ); +#else + TextFocused( "->", RealToString( ev.cpu, true ) ); +#endif + } + else + { + TextFocused( "CPU:", RealToString( ev.cpu, true ) ); + } + TextFocused( "Wait reason:", DecodeContextSwitchReasonCode( ContextSwitchData::Reason( *pit ) ) ); + ImGui::SameLine(); + TextDisabledUnformatted( DecodeContextSwitchReason( ContextSwitchData::Reason( *pit ) ) ); + TextFocused( "Wait state:", DecodeContextSwitchStateCode( ContextSwitchData::State( *pit ) ) ); + ImGui::SameLine(); + TextDisabledUnformatted( DecodeContextSwitchState( ContextSwitchData::State( *pit ) ) ); + ImGui::EndTooltip(); + + if( ImGui::IsMouseClicked( 2 ) ) + { + ZoomToRange( pit->end, ev.start ); + } + } } const auto end = ev.end >= 0 ? ev.end : m_worker.GetLastTime(); @@ -2256,10 +2391,36 @@ void View::DrawContextSwitches( const ContextSwitch* ctx, double pxns, int64_t n if( num == 1 ) { draw->AddLine( wpos + ImVec2( px0, round( offset + ty * 0.5 ) - 0.5 ), wpos + ImVec2( minpx, round( offset + ty * 0.5 ) - 0.5 ), 0xFF22DD22, 2 ); + if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty ) ) ) + { + ImGui::BeginTooltip(); + TextFocused( "Thread is", "running" ); + TextFocused( "Activity time:", TimeToString( end - ev.start ) ); + TextFocused( "CPU:", RealToString( ev.cpu, true ) ); + ImGui::EndTooltip(); + + if( ImGui::IsMouseClicked( 2 ) ) + { + ZoomToRange( ev.start, rend ); + } + } } else { DrawZigZag( draw, wpos + ImVec2( 0, offset + round( ty/2 ) ), px0, minpx, ty/4, 0xFF888888, 1.5 ); + if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( minpx, offset + ty ) ) ) + { + ImGui::BeginTooltip(); + TextFocused( "Thread is", "chaning activity multiple times" ); + TextFocused( "Number of running regions:", RealToString( num, true ) ); + TextFocused( "Time:", TimeToString( rend - ev.start ) ); + ImGui::EndTooltip(); + + if( ImGui::IsMouseClicked( 2 ) ) + { + ZoomToRange( ev.start, rend ); + } + } } pit = it-1; } @@ -2268,6 +2429,19 @@ void View::DrawContextSwitches( const ContextSwitch* ctx, double pxns, int64_t n const auto px0 = std::max( { ( ev.start - m_zvStart ) * pxns, -10.0, minpx } ); const auto px1 = std::min( ( end - m_zvStart ) * pxns, w + 10.0 ); draw->AddLine( wpos + ImVec2( px0, round( offset + ty * 0.5 ) - 0.5 ), wpos + ImVec2( px1, round( offset + ty * 0.5 ) - 0.5 ), 0xFF22DD22, 2 ); + if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + ty ) ) ) + { + ImGui::BeginTooltip(); + TextFocused( "Thread is", "running" ); + TextFocused( "Activity time:", TimeToString( end - ev.start ) ); + TextFocused( "CPU:", RealToString( ev.cpu, true ) ); + ImGui::EndTooltip(); + + if( ImGui::IsMouseClicked( 2 ) ) + { + ZoomToRange( ev.start, end ); + } + } pit = it; ++it; } |