mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-22 22:44:34 +00:00
Pack ContextSwitchData. Saves 3 bytes per context switch region.
This commit is contained in:
parent
e90ddf7ee5
commit
889eddd646
@ -234,11 +234,19 @@ enum { CrashEventSize = sizeof( CrashEvent ) };
|
||||
|
||||
struct ContextSwitchData
|
||||
{
|
||||
int64_t start;
|
||||
int64_t end;
|
||||
uint8_t cpu;
|
||||
int8_t reason;
|
||||
int8_t state;
|
||||
int64_t Start() const { return int64_t( _start_cpu ) >> 8; }
|
||||
void SetStart( int64_t start ) { assert( start < ( 1ll << 47 ) ); _start_cpu = ( _start_cpu & 0xFF ) | uint64_t( start << 8 ); }
|
||||
int64_t End() const { return int64_t( _end_reason_state ) >> 16; }
|
||||
void SetEnd( int64_t end ) { assert( end < ( 1ll << 47 ) ); _end_reason_state = ( _end_reason_state & 0xFFFF ) | uint64_t( end << 16 ); }
|
||||
uint8_t Cpu() const { return uint8_t( _start_cpu & 0xFF ); }
|
||||
void SetCpu( uint8_t cpu ) { _start_cpu = ( _start_cpu & 0xFFFFFFFFFFFFFF00 ) | uint8_t( cpu ); }
|
||||
int8_t Reason() const { return int8_t( (_end_reason_state >> 8) & 0xFF ); }
|
||||
void SetReason( int8_t reason ) { _end_reason_state = ( _end_reason_state & 0xFFFFFFFFFFFF00FF ) | ( uint64_t( reason ) << 8 ); }
|
||||
int8_t State() const { return int8_t( _end_reason_state & 0xFF ); }
|
||||
void SetState( int8_t state ) { _end_reason_state = ( _end_reason_state & 0xFFFFFFFFFFFFFF00 ) | uint8_t( state ); }
|
||||
|
||||
uint64_t _start_cpu;
|
||||
uint64_t _end_reason_state;
|
||||
};
|
||||
|
||||
enum { ContextSwitchDataSize = sizeof( ContextSwitchData ) };
|
||||
|
@ -2068,8 +2068,8 @@ void View::DrawZones()
|
||||
if( ctx && !ctx->v.empty() )
|
||||
{
|
||||
const auto& back = ctx->v.back();
|
||||
first = ctx->v.begin()->start;
|
||||
last = back.end >= 0 ? back.end : back.start;
|
||||
first = ctx->v.begin()->Start();
|
||||
last = back.End() >= 0 ? back.End() : back.Start();
|
||||
}
|
||||
if( !v->timeline.empty() )
|
||||
{
|
||||
@ -2343,11 +2343,11 @@ static const char* DecodeContextSwitchState( uint8_t state )
|
||||
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; } );
|
||||
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; } );
|
||||
if( it == vec.end() ) return;
|
||||
if( it != vec.begin() ) --it;
|
||||
|
||||
auto citend = std::lower_bound( it, vec.end(), m_zvEnd, [] ( const auto& l, const auto& r ) { return l.start < r; } );
|
||||
auto citend = std::lower_bound( it, vec.end(), m_zvEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );
|
||||
if( it == citend ) return;
|
||||
if( citend != vec.end() ) ++citend;
|
||||
|
||||
@ -2363,9 +2363,9 @@ void View::DrawContextSwitches( const ContextSwitch* ctx, bool hover, double pxn
|
||||
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 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 = 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 );
|
||||
|
||||
@ -2373,56 +2373,56 @@ void View::DrawContextSwitches( const ContextSwitch* ctx, bool hover, double pxn
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "Thread is", migration ? "migrating CPUs" : "waiting" );
|
||||
TextFocused( "Waiting time:", TimeToString( ev.start - pit->end ) );
|
||||
TextFocused( "Waiting time:", TimeToString( ev.Start() - pit->End() ) );
|
||||
if( migration )
|
||||
{
|
||||
TextFocused( "CPU:", RealToString( pit->cpu, true ) );
|
||||
TextFocused( "CPU:", RealToString( pit->Cpu(), true ) );
|
||||
ImGui::SameLine();
|
||||
#ifdef TRACY_EXTENDED_FONT
|
||||
TextFocused( ICON_FA_LONG_ARROW_ALT_RIGHT, RealToString( ev.cpu, true ) );
|
||||
TextFocused( ICON_FA_LONG_ARROW_ALT_RIGHT, RealToString( ev.Cpu(), true ) );
|
||||
#else
|
||||
TextFocused( "->", RealToString( ev.cpu, true ) );
|
||||
TextFocused( "->", RealToString( ev.Cpu(), true ) );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
TextFocused( "CPU:", RealToString( ev.cpu, true ) );
|
||||
TextFocused( "CPU:", RealToString( ev.Cpu(), true ) );
|
||||
}
|
||||
if( pit->reason != 100 )
|
||||
if( pit->Reason() != 100 )
|
||||
{
|
||||
TextFocused( "Wait reason:", DecodeContextSwitchReasonCode( pit->reason ) );
|
||||
TextFocused( "Wait reason:", DecodeContextSwitchReasonCode( pit->Reason() ) );
|
||||
ImGui::SameLine();
|
||||
TextDisabledUnformatted( DecodeContextSwitchReason( pit->reason ) );
|
||||
TextDisabledUnformatted( DecodeContextSwitchReason( pit->Reason() ) );
|
||||
}
|
||||
TextFocused( "Wait state:", DecodeContextSwitchStateCode( pit->state ) );
|
||||
TextFocused( "Wait state:", DecodeContextSwitchStateCode( pit->State() ) );
|
||||
ImGui::SameLine();
|
||||
TextDisabledUnformatted( DecodeContextSwitchState( pit->state ) );
|
||||
TextDisabledUnformatted( DecodeContextSwitchState( pit->State() ) );
|
||||
ImGui::EndTooltip();
|
||||
|
||||
if( ImGui::IsMouseClicked( 2 ) )
|
||||
{
|
||||
ZoomToRange( pit->end, ev.start );
|
||||
ZoomToRange( pit->End(), ev.Start() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto end = ev.end >= 0 ? ev.end : m_worker.GetLastTime();
|
||||
const auto zsz = std::max( ( end - ev.start ) * pxns, pxns * 0.5 );
|
||||
const auto end = ev.End() >= 0 ? ev.End() : m_worker.GetLastTime();
|
||||
const auto zsz = std::max( ( end - ev.Start() ) * pxns, pxns * 0.5 );
|
||||
if( zsz < MinCtxSize )
|
||||
{
|
||||
int num = 0;
|
||||
const auto px0 = std::max( ( ev.start - m_zvStart ) * pxns, -10.0 );
|
||||
const auto px0 = std::max( ( ev.Start() - m_zvStart ) * pxns, -10.0 );
|
||||
auto px1 = ( end - m_zvStart ) * pxns;
|
||||
auto rend = end;
|
||||
auto nextTime = end + MinCtxSize;
|
||||
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; } );
|
||||
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->end >= 0 ? it->end : m_worker.GetLastTime();
|
||||
const auto nend = it->End() >= 0 ? it->End() : m_worker.GetLastTime();
|
||||
const auto pxnext = ( nend - m_zvStart ) * pxns;
|
||||
if( pxnext - px1 >= MinCtxSize * 2 ) break;
|
||||
px1 = pxnext;
|
||||
@ -2437,13 +2437,13 @@ void View::DrawContextSwitches( const ContextSwitch* ctx, bool hover, double pxn
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "Thread is", "running" );
|
||||
TextFocused( "Activity time:", TimeToString( end - ev.start ) );
|
||||
TextFocused( "CPU:", RealToString( ev.cpu, true ) );
|
||||
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
||||
TextFocused( "CPU:", RealToString( ev.Cpu(), true ) );
|
||||
ImGui::EndTooltip();
|
||||
|
||||
if( ImGui::IsMouseClicked( 2 ) )
|
||||
{
|
||||
ZoomToRange( ev.start, rend );
|
||||
ZoomToRange( ev.Start(), rend );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2455,12 +2455,12 @@ void View::DrawContextSwitches( const ContextSwitch* ctx, bool hover, double pxn
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "Thread is", "chaning activity multiple times" );
|
||||
TextFocused( "Number of running regions:", RealToString( num, true ) );
|
||||
TextFocused( "Time:", TimeToString( rend - ev.start ) );
|
||||
TextFocused( "Time:", TimeToString( rend - ev.Start() ) );
|
||||
ImGui::EndTooltip();
|
||||
|
||||
if( ImGui::IsMouseClicked( 2 ) )
|
||||
{
|
||||
ZoomToRange( ev.start, rend );
|
||||
ZoomToRange( ev.Start(), rend );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2468,20 +2468,20 @@ void View::DrawContextSwitches( const ContextSwitch* ctx, bool hover, double pxn
|
||||
}
|
||||
else
|
||||
{
|
||||
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 );
|
||||
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 ) );
|
||||
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
||||
TextFocused( "CPU:", RealToString( ev.Cpu(), true ) );
|
||||
ImGui::EndTooltip();
|
||||
|
||||
if( ImGui::IsMouseClicked( 2 ) )
|
||||
{
|
||||
ZoomToRange( ev.start, end );
|
||||
ZoomToRange( ev.Start(), end );
|
||||
}
|
||||
}
|
||||
pit = it;
|
||||
@ -4686,11 +4686,11 @@ void View::DrawZoneInfoWindow()
|
||||
const auto ctx = m_worker.GetContextSwitchData( tid );
|
||||
if( ctx )
|
||||
{
|
||||
auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.end < (uint64_t)r; } );
|
||||
auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
|
||||
if( it != ctx->v.end() )
|
||||
{
|
||||
const auto end = m_worker.GetZoneEnd( ev );
|
||||
auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.start; } );
|
||||
auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.Start(); } );
|
||||
bool incomplete = eit == ctx->v.end();
|
||||
uint64_t cnt = std::distance( it, eit );
|
||||
if( cnt == 1 )
|
||||
@ -4702,24 +4702,24 @@ void View::DrawZoneInfoWindow()
|
||||
TextDisabledUnformatted( "(100%)" );
|
||||
ImGui::Separator();
|
||||
TextFocused( "Running state regions:", "1" );
|
||||
TextFocused( "CPU:", RealToString( it->cpu, true ) );
|
||||
TextFocused( "CPU:", RealToString( it->Cpu(), true ) );
|
||||
}
|
||||
}
|
||||
else if( cnt > 1 )
|
||||
{
|
||||
uint8_t cpus[256] = {};
|
||||
auto bit = it;
|
||||
int64_t running = it->end - ev.Start();
|
||||
cpus[it->cpu] = 1;
|
||||
int64_t running = it->End() - ev.Start();
|
||||
cpus[it->Cpu()] = 1;
|
||||
++it;
|
||||
for( int64_t i=0; i<cnt-2; i++ )
|
||||
{
|
||||
running += it->end - it->start;
|
||||
cpus[it->cpu] = 1;
|
||||
running += it->End() - it->Start();
|
||||
cpus[it->Cpu()] = 1;
|
||||
++it;
|
||||
}
|
||||
running += end - it->start;
|
||||
cpus[it->cpu] = 1;
|
||||
running += end - it->Start();
|
||||
cpus[it->Cpu()] = 1;
|
||||
TextFocused( "Running state time:", TimeToString( running ) );
|
||||
if( ztime != 0 )
|
||||
{
|
||||
@ -4737,7 +4737,7 @@ void View::DrawZoneInfoWindow()
|
||||
for( int i=0; i<256; i++ ) numCpus += cpus[i];
|
||||
if( numCpus == 1 )
|
||||
{
|
||||
TextFocused( "CPU:", RealToString( it->cpu, true ) );
|
||||
TextFocused( "CPU:", RealToString( it->Cpu(), true ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4781,13 +4781,13 @@ void View::DrawZoneInfoWindow()
|
||||
ImGui::Separator();
|
||||
while( bit < eit )
|
||||
{
|
||||
const auto cend = bit->end;
|
||||
const auto state = bit->state;
|
||||
const auto reason = bit->reason;
|
||||
const auto cpu0 = bit->cpu;
|
||||
const auto cend = bit->End();
|
||||
const auto state = bit->State();
|
||||
const auto reason = bit->Reason();
|
||||
const auto cpu0 = bit->Cpu();
|
||||
++bit;
|
||||
const auto cstart = bit->start;
|
||||
const auto cpu1 = bit->cpu;
|
||||
const auto cstart = bit->Start();
|
||||
const auto cpu1 = bit->Cpu();
|
||||
|
||||
ImGui::TextUnformatted( TimeToString( cend - adjust ) );
|
||||
if( ImGui::IsMouseClicked( 0 ) && ImGui::IsItemHovered() ) CenterAtTime( cend );
|
||||
@ -11740,10 +11740,10 @@ int64_t View::GetZoneSelfTime( const GpuEvent& zone )
|
||||
|
||||
bool View::GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, int64_t& time, uint64_t& cnt )
|
||||
{
|
||||
auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.end < (uint64_t)r; } );
|
||||
auto it = std::lower_bound( ctx->v.begin(), ctx->v.end(), ev.Start(), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
|
||||
if( it == ctx->v.end() ) return false;
|
||||
const auto end = m_worker.GetZoneEnd( ev );
|
||||
const auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.start; } );
|
||||
const auto eit = std::upper_bound( it, ctx->v.end(), end, [] ( const auto& l, const auto& r ) { return l < r.Start(); } );
|
||||
if( eit == ctx->v.end() ) return false;
|
||||
cnt = std::distance( it, eit );
|
||||
if( cnt == 0 ) return false;
|
||||
@ -11753,14 +11753,14 @@ bool View::GetZoneRunningTime( const ContextSwitch* ctx, const ZoneEvent& ev, in
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t running = it->end - ev.Start();
|
||||
int64_t running = it->End() - ev.Start();
|
||||
++it;
|
||||
for( int64_t i=0; i<cnt-2; i++ )
|
||||
{
|
||||
running += it->end - it->start;
|
||||
running += it->End() - it->Start();
|
||||
++it;
|
||||
}
|
||||
running += end - it->start;
|
||||
running += end - it->Start();
|
||||
time = running;
|
||||
}
|
||||
return true;
|
||||
|
@ -1399,13 +1399,21 @@ Worker::Worker( FileRead& f, EventType::Type eventMask )
|
||||
auto ptr = data->v.data();
|
||||
for( uint64_t j=0; j<csz; j++ )
|
||||
{
|
||||
ptr->start = ReadTimeOffset( f, refTime );
|
||||
ptr->SetStart( ReadTimeOffset( f, refTime ) );
|
||||
int64_t diff;
|
||||
f.Read( diff );
|
||||
if( diff > 0 ) runningTime += diff;
|
||||
refTime += diff;
|
||||
ptr->end = refTime;
|
||||
f.Read( &ptr->cpu, sizeof( ptr->cpu ) + sizeof( ptr->reason ) + sizeof( ptr->state ) );
|
||||
ptr->SetEnd( refTime );
|
||||
uint8_t cpu;
|
||||
int8_t reason;
|
||||
int8_t state;
|
||||
f.Read( cpu );
|
||||
f.Read( reason );
|
||||
f.Read( state );
|
||||
ptr->SetCpu( cpu );
|
||||
ptr->SetReason( reason );
|
||||
ptr->SetState( state );
|
||||
ptr++;
|
||||
}
|
||||
data->runningTime = runningTime;
|
||||
@ -3969,12 +3977,12 @@ void Worker::ProcessContextSwitch( const QueueContextSwitch& ev )
|
||||
auto& data = it->second->v;
|
||||
assert( !data.empty() );
|
||||
auto& item = data.back();
|
||||
assert( item.start <= time );
|
||||
item.end = time;
|
||||
item.reason = ev.reason;
|
||||
item.state = ev.state;
|
||||
assert( item.Start() <= time );
|
||||
item.SetEnd( time );
|
||||
item.SetReason( ev.reason );
|
||||
item.SetState( ev.state );
|
||||
|
||||
it->second->runningTime += time - item.start;
|
||||
it->second->runningTime += time - item.Start();
|
||||
}
|
||||
}
|
||||
if( ev.newThread != 0 )
|
||||
@ -3986,13 +3994,13 @@ void Worker::ProcessContextSwitch( const QueueContextSwitch& ev )
|
||||
it = m_data.ctxSwitch.emplace( ev.newThread, ctx ).first;
|
||||
}
|
||||
auto& data = it->second->v;
|
||||
assert( data.empty() || (uint64_t)data.back().end <= time );
|
||||
assert( data.empty() || (uint64_t)data.back().End() <= time );
|
||||
auto& item = data.push_next();
|
||||
item.start = time;
|
||||
item.end = -1;
|
||||
item.cpu = ev.cpu;
|
||||
item.reason = -1;
|
||||
item.state = -1;
|
||||
item.SetStart( time );
|
||||
item.SetEnd( -1 );
|
||||
item.SetCpu( ev.cpu );
|
||||
item.SetReason( -1 );
|
||||
item.SetState( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -4793,9 +4801,14 @@ void Worker::Write( FileWrite& f )
|
||||
int64_t refTime = 0;
|
||||
for( auto& cs : ctx->second->v )
|
||||
{
|
||||
WriteTimeOffset( f, refTime, cs.start );
|
||||
WriteTimeOffset( f, refTime, cs.end );
|
||||
f.Write( &cs.cpu, sizeof( cs.cpu ) + sizeof( cs.reason ) + sizeof( cs.state ) );
|
||||
WriteTimeOffset( f, refTime, cs.Start() );
|
||||
WriteTimeOffset( f, refTime, cs.End() );
|
||||
uint8_t cpu = cs.Cpu();
|
||||
int8_t reason = cs.Reason();
|
||||
int8_t state = cs.State();
|
||||
f.Write( &cpu, sizeof( cpu ) );
|
||||
f.Write( &reason, sizeof( reason ) );
|
||||
f.Write( &state, sizeof( state ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user