Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/wolfpld/tracy.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Taudul <wolf.pld@gmail.com>2019-08-13 16:10:44 +0300
committerBartosz Taudul <wolf.pld@gmail.com>2019-08-13 17:20:43 +0300
commit71a5cffc137d3508c58907b2e491192de9b59e2d (patch)
treecf5a253fc98a67eb5647fb4c1f1132a633dc539e /server/TracyView.cpp
parentf285e0f5cc063e60b5c889ca5082cbd65add0843 (diff)
Add context switch tooltips.
Diffstat (limited to 'server/TracyView.cpp')
-rw-r--r--server/TracyView.cpp180
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;
}