mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-14 04:01:48 +00:00
Add context switch tooltips.
This commit is contained in:
parent
f285e0f5cc
commit
71a5cffc13
@ -1888,7 +1888,7 @@ void View::DrawZones()
|
|||||||
auto ctxSwitch = m_worker.GetContextSwitchData( v->id );
|
auto ctxSwitch = m_worker.GetContextSwitchData( v->id );
|
||||||
if( ctxSwitch )
|
if( ctxSwitch )
|
||||||
{
|
{
|
||||||
DrawContextSwitches( ctxSwitch, pxns, int64_t( nspx ), wpos, offset );
|
DrawContextSwitches( ctxSwitch, hover, pxns, int64_t( nspx ), wpos, offset );
|
||||||
offset += round( ostep * 0.75f );
|
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& 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; } );
|
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;
|
auto& ev = *it;
|
||||||
if( pit != citend )
|
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 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 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 );
|
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();
|
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 )
|
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 );
|
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
|
else
|
||||||
{
|
{
|
||||||
DrawZigZag( draw, wpos + ImVec2( 0, offset + round( ty/2 ) ), px0, minpx, ty/4, 0xFF888888, 1.5 );
|
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;
|
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 px0 = std::max( { ( ev.start - m_zvStart ) * pxns, -10.0, minpx } );
|
||||||
const auto px1 = std::min( ( end - m_zvStart ) * pxns, w + 10.0 );
|
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 );
|
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;
|
pit = it;
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ private:
|
|||||||
bool DrawZoneFramesHeader();
|
bool DrawZoneFramesHeader();
|
||||||
bool DrawZoneFrames( const FrameData& frames );
|
bool DrawZoneFrames( const FrameData& frames );
|
||||||
void DrawZones();
|
void DrawZones();
|
||||||
void DrawContextSwitches( const ContextSwitch* ctx, double pxns, int64_t nspx, const ImVec2& wpos, int offset );
|
void DrawContextSwitches( const ContextSwitch* ctx, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset );
|
||||||
int DispatchZoneLevel( const Vector<ZoneEvent*>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, float yMin, float yMax );
|
int DispatchZoneLevel( const Vector<ZoneEvent*>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, float yMin, float yMax );
|
||||||
int DrawZoneLevel( const Vector<ZoneEvent*>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, float yMin, float yMax );
|
int DrawZoneLevel( const Vector<ZoneEvent*>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, float yMin, float yMax );
|
||||||
int SkipZoneLevel( const Vector<ZoneEvent*>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, float yMin, float yMax );
|
int SkipZoneLevel( const Vector<ZoneEvent*>& vec, bool hover, double pxns, int64_t nspx, const ImVec2& wpos, int offset, int depth, float yMin, float yMax );
|
||||||
|
Loading…
Reference in New Issue
Block a user