mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-22 14:44:34 +00:00
Parallelize calculation of per-CPU context switches.
This commit is contained in:
parent
a4c200d242
commit
2b7b79352b
@ -63,6 +63,14 @@ struct CpuUsageDraw
|
||||
int other;
|
||||
};
|
||||
|
||||
|
||||
struct CpuCtxDraw
|
||||
{
|
||||
uint32_t idx;
|
||||
uint32_t num;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -41,18 +41,20 @@ int64_t TimelineItemCpuData::RangeEnd() const
|
||||
|
||||
bool TimelineItemCpuData::DrawContents( const TimelineContext& ctx, int& offset )
|
||||
{
|
||||
m_view.DrawCpuData( ctx, m_cpuDraw, offset );
|
||||
m_view.DrawCpuData( ctx, m_cpuDraw, m_ctxDraw, offset );
|
||||
return true;
|
||||
}
|
||||
|
||||
void TimelineItemCpuData::DrawFinished()
|
||||
{
|
||||
m_cpuDraw.clear();
|
||||
for( auto& v : m_ctxDraw ) v.clear();
|
||||
}
|
||||
|
||||
void TimelineItemCpuData::Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible )
|
||||
{
|
||||
assert( m_cpuDraw.empty() );
|
||||
for( auto& v : m_ctxDraw ) assert( v.empty() );
|
||||
|
||||
if( !visible ) return;
|
||||
|
||||
@ -66,6 +68,65 @@ void TimelineItemCpuData::Preprocess( const TimelineContext& ctx, TaskDispatch&
|
||||
PreprocessCpuUsage( ctx );
|
||||
} );
|
||||
}
|
||||
|
||||
auto cpuData = m_worker.GetCpuData();
|
||||
const auto cpuCnt = m_worker.GetCpuDataCpuCount();
|
||||
if( m_ctxDraw.size() != cpuCnt ) m_ctxDraw.resize( cpuCnt );
|
||||
|
||||
for( int i=0; i<cpuCnt; i++ )
|
||||
{
|
||||
auto& cs = cpuData[i].cs;
|
||||
if( !cs.empty() )
|
||||
{
|
||||
td.Queue( [this, &ctx, &cs, i] {
|
||||
PreprocessCpuCtxSwitches( ctx, cs, m_ctxDraw[i] );
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr float MinVisSize = 3;
|
||||
|
||||
void TimelineItemCpuData::PreprocessCpuCtxSwitches( const TimelineContext& ctx, const Vector<ContextSwitchCpu>& cs, std::vector<CpuCtxDraw>& out )
|
||||
{
|
||||
const auto vStart = ctx.vStart;
|
||||
const auto vEnd = ctx.vEnd;
|
||||
const auto nspx = ctx.nspx;
|
||||
|
||||
auto it = std::lower_bound( cs.begin(), cs.end(), std::max<int64_t>( 0, vStart ), [this] ( const auto& l, const auto& r ) { return ( l.IsEndValid() ? l.End() : m_worker.GetLastTime() ) < r; } );
|
||||
if( it == cs.end() ) return;
|
||||
auto eit = std::lower_bound( it, cs.end(), vEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );
|
||||
if( it == eit ) return;
|
||||
|
||||
const auto MinVisNs = int64_t( round( GetScale() * MinVisSize * nspx ) );
|
||||
|
||||
while( it < eit )
|
||||
{
|
||||
const auto end = it->IsEndValid() ? it->End() : m_worker.GetLastTime();
|
||||
const auto zsz = end - it->Start();
|
||||
if( zsz < MinVisNs )
|
||||
{
|
||||
auto nextTime = end + MinVisNs;
|
||||
auto next = it + 1;
|
||||
for(;;)
|
||||
{
|
||||
next = std::lower_bound( next, eit, nextTime, [this] ( const auto& l, const auto& r ) { return ( l.IsEndValid() ? l.End() : m_worker.GetLastTime() ) < r; } );
|
||||
if( next == eit ) 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 >= MinVisNs ) break;
|
||||
nextTime = nt + MinVisNs;
|
||||
}
|
||||
out.emplace_back( CpuCtxDraw { uint32_t( it - cs.begin() ), uint32_t( next - it ) } );
|
||||
it = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
out.emplace_back( CpuCtxDraw { uint32_t( it - cs.begin() ), 0 } );
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineItemCpuData::PreprocessCpuUsage( const TimelineContext& ctx )
|
||||
|
@ -34,8 +34,10 @@ protected:
|
||||
|
||||
private:
|
||||
void PreprocessCpuUsage( const TimelineContext& ctx );
|
||||
void PreprocessCpuCtxSwitches( const TimelineContext& ctx, const Vector<ContextSwitchCpu>& cs, std::vector<CpuCtxDraw>& out );
|
||||
|
||||
std::vector<CpuUsageDraw> m_cpuDraw;
|
||||
std::vector<std::vector<CpuCtxDraw>> m_ctxDraw;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ struct ContextSwitchDraw;
|
||||
struct SamplesDraw;
|
||||
struct MessagesDraw;
|
||||
struct CpuUsageDraw;
|
||||
struct CpuCtxDraw;
|
||||
|
||||
class View
|
||||
{
|
||||
@ -132,7 +133,7 @@ public:
|
||||
void DrawThreadMessagesList( const TimelineContext& ctx, const std::vector<MessagesDraw>& drawList, int offset, uint64_t tid );
|
||||
void DrawThreadOverlays( const ThreadData& thread, const ImVec2& ul, const ImVec2& dr );
|
||||
bool DrawGpu( const TimelineContext& ctx, const GpuCtxData& gpu, int& offset );
|
||||
bool DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDraw>&, int& offset );
|
||||
bool DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDraw>& cpuDraw, const std::vector<std::vector<CpuCtxDraw>>& ctxDraw, int& offset );
|
||||
|
||||
bool m_showRanges = false;
|
||||
Range m_statRange;
|
||||
|
@ -9,12 +9,12 @@
|
||||
#include "TracyTimelineContext.hpp"
|
||||
#include "TracyView.hpp"
|
||||
|
||||
constexpr float MinVisSize = 3;
|
||||
|
||||
namespace tracy
|
||||
{
|
||||
|
||||
constexpr float MinVisSize = 3;
|
||||
|
||||
bool View::DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDraw>& cpuDraw, int& offset )
|
||||
bool View::DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDraw>& cpuDraw, const std::vector<std::vector<CpuCtxDraw>>& ctxDraw, int& offset )
|
||||
{
|
||||
auto cpuData = m_worker.GetCpuData();
|
||||
const auto cpuCnt = m_worker.GetCpuDataCpuCount();
|
||||
@ -30,6 +30,7 @@ bool View::DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDr
|
||||
const auto yMin = ctx.yMin;
|
||||
const auto yMax = ctx.yMax;
|
||||
const auto hover = ctx.hover;
|
||||
const auto vStart = ctx.vStart;
|
||||
|
||||
auto draw = ImGui::GetWindowDrawList();
|
||||
|
||||
@ -146,243 +147,215 @@ bool View::DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDr
|
||||
const auto origOffset = offset;
|
||||
for( int i=0; i<cpuCnt; i++ )
|
||||
{
|
||||
if( !cpuData[i].cs.empty() )
|
||||
DrawLine( draw, dpos + ImVec2( 0, offset+sty ), dpos + ImVec2( w, offset+sty ), 0x22DD88DD );
|
||||
auto tt = m_worker.GetThreadTopology( i );
|
||||
if( !ctxDraw[i].empty() && wpos.y + offset + sty >= yMin && wpos.y + offset <= yMax )
|
||||
{
|
||||
if( wpos.y + offset + sty >= yMin && wpos.y + offset <= yMax )
|
||||
auto& cs = cpuData[i].cs;
|
||||
for( auto& v : ctxDraw[i] )
|
||||
{
|
||||
DrawLine( draw, dpos + ImVec2( 0, offset+sty ), dpos + ImVec2( w, offset+sty ), 0x22DD88DD );
|
||||
|
||||
auto& cs = cpuData[i].cs;
|
||||
auto tt = m_worker.GetThreadTopology( i );
|
||||
|
||||
auto it = std::lower_bound( cs.begin(), cs.end(), std::max<int64_t>( 0, m_vd.zvStart ), [] ( const auto& l, const auto& r ) { return (uint64_t)l.End() < (uint64_t)r; } );
|
||||
if( it != cs.end() )
|
||||
const auto& ev = cs[v.idx];
|
||||
const auto t0 = ev.Start();
|
||||
const auto px0 = ( t0 - vStart ) * pxns;
|
||||
if( v.num > 0 )
|
||||
{
|
||||
auto eit = std::lower_bound( it, cs.end(), m_vd.zvEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );
|
||||
while( it < eit )
|
||||
const auto& eev = cs[v.idx + v.num - 1];
|
||||
const auto t1 = eev.IsEndValid() ? eev.End() : m_worker.GetLastTime();
|
||||
const auto px1 = ( t1 - vStart ) * pxns;
|
||||
DrawZigZag( draw, wpos + ImVec2( 0, offset + sty/2 ), std::max( px0, -10.0 ), std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), sty/4, 0xFF888888 );
|
||||
|
||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset-1 ), wpos + ImVec2( std::max( px1, px0+MinVisSize ), offset + sty ) ) )
|
||||
{
|
||||
const auto start = it->Start();
|
||||
const auto end = it->End();
|
||||
const auto zsz = std::max( ( end - start ) * pxns, pxns * 0.5 );
|
||||
if( zsz < MinVisSize )
|
||||
ImGui::PopFont();
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "CPU:", RealToString( i ) );
|
||||
if( tt )
|
||||
{
|
||||
const auto MinVisNs = MinVisSize * nspx;
|
||||
int num = 0;
|
||||
const auto px0 = ( start - m_vd.zvStart ) * pxns;
|
||||
auto px1ns = end - m_vd.zvStart;
|
||||
auto rend = end;
|
||||
auto nextTime = end + MinVisNs;
|
||||
for(;;)
|
||||
{
|
||||
const auto prevIt = it;
|
||||
it = std::lower_bound( it, eit, 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 == eit ) break;
|
||||
const auto nend = it->IsEndValid() ? it->End() : m_worker.GetLastTime();
|
||||
const auto nsnext = nend - m_vd.zvStart;
|
||||
if( nsnext - px1ns >= MinVisNs * 2 ) break;
|
||||
px1ns = nsnext;
|
||||
rend = nend;
|
||||
nextTime = nend + nspx;
|
||||
}
|
||||
const auto px1 = px1ns * pxns;
|
||||
DrawZigZag( draw, wpos + ImVec2( 0, offset + sty/2 ), std::max( px0, -10.0 ), std::min( std::max( px1, px0+MinVisSize ), double( w + 10 ) ), sty/4, 0xFF888888 );
|
||||
|
||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset-1 ), wpos + ImVec2( std::max( px1, px0+MinVisSize ), offset + sty ) ) )
|
||||
{
|
||||
ImGui::PopFont();
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "CPU:", RealToString( i ) );
|
||||
if( tt )
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Package:", RealToString( tt->package ) );
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Core:", RealToString( tt->core ) );
|
||||
}
|
||||
TextFocused( "Context switch regions:", RealToString( num ) );
|
||||
ImGui::Separator();
|
||||
TextFocused( "Start time:", TimeToString( start ) );
|
||||
TextFocused( "End time:", TimeToString( rend ) );
|
||||
TextFocused( "Activity time:", TimeToString( rend - start ) );
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PushFont( m_smallFont );
|
||||
|
||||
if( IsMouseClicked( 2 ) )
|
||||
{
|
||||
ZoomToRange( start, rend );
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Package:", RealToString( tt->package ) );
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Core:", RealToString( tt->core ) );
|
||||
}
|
||||
else
|
||||
TextFocused( "Context switch regions:", RealToString( v.num ) );
|
||||
ImGui::Separator();
|
||||
TextFocused( "Start time:", TimeToString( t0 ) );
|
||||
TextFocused( "End time:", TimeToString( t1 ) );
|
||||
TextFocused( "Activity time:", TimeToString( t1 - t0 ) );
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PushFont( m_smallFont );
|
||||
|
||||
if( IsMouseClicked( 2 ) )
|
||||
{
|
||||
const auto thread = m_worker.DecompressThreadExternal( it->Thread() );
|
||||
bool local, untracked;
|
||||
const char* txt;
|
||||
auto label = GetThreadContextData( thread, local, untracked, txt );
|
||||
const auto pr0 = ( start - m_vd.zvStart ) * pxns;
|
||||
const auto pr1 = ( end - m_vd.zvStart ) * pxns;
|
||||
const auto px0 = std::max( pr0, -10.0 );
|
||||
const auto px1 = std::max( { std::min( pr1, double( w + 10 ) ), px0 + pxns * 0.5, px0 + MinVisSize } );
|
||||
|
||||
uint32_t color;
|
||||
if( m_vd.dynamicColors != 0 )
|
||||
{
|
||||
color = local ? GetThreadColor( thread, 0 ) : ( untracked ? 0xFF663333 : 0xFF444444 );
|
||||
}
|
||||
else
|
||||
{
|
||||
color = local ? 0xFF334488 : ( untracked ? 0xFF663333 : 0xFF444444 );
|
||||
}
|
||||
|
||||
draw->AddRectFilled( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + sty ), color );
|
||||
if( m_drawThreadHighlight == thread )
|
||||
{
|
||||
draw->AddRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + sty ), 0xFFFFFFFF );
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto accentColor = HighlightColor( color );
|
||||
const auto darkColor = DarkenColor( color );
|
||||
DrawLine( draw, dpos + ImVec2( px0, offset + sty ), dpos + ImVec2( px0, offset ), dpos + ImVec2( px1-1, offset ), accentColor, 1.f );
|
||||
DrawLine( draw, dpos + ImVec2( px0, offset + sty ), dpos + ImVec2( px1-1, offset + sty ), dpos + ImVec2( px1-1, offset ), darkColor, 1.f );
|
||||
}
|
||||
|
||||
auto tsz = ImGui::CalcTextSize( label );
|
||||
if( tsz.x < zsz )
|
||||
{
|
||||
const auto x = ( start - m_vd.zvStart ) * pxns + ( ( end - start ) * pxns - tsz.x ) / 2;
|
||||
if( x < 0 || x > w - tsz.x )
|
||||
{
|
||||
ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );
|
||||
DrawTextContrast( draw, wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
else if( start == end )
|
||||
{
|
||||
DrawTextContrast( draw, wpos + ImVec2( px0 + ( px1 - px0 - tsz.x ) * 0.5, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTextContrast( draw, wpos + ImVec2( x, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );
|
||||
DrawTextContrast( draw, wpos + ImVec2( ( start - m_vd.zvStart ) * pxns, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
|
||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset-1 ), wpos + ImVec2( px1, offset + sty ) ) )
|
||||
{
|
||||
m_drawThreadHighlight = thread;
|
||||
ImGui::PopFont();
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "CPU:", RealToString( i ) );
|
||||
if( tt )
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Package:", RealToString( tt->package ) );
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Core:", RealToString( tt->core ) );
|
||||
}
|
||||
if( local )
|
||||
{
|
||||
TextFocused( "Program:", m_worker.GetCaptureProgram().c_str() );
|
||||
ImGui::SameLine();
|
||||
TextDisabledUnformatted( "(profiled program)" );
|
||||
SmallColorBox( GetThreadColor( thread, 0 ) );
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Thread:", m_worker.GetThreadName( thread ) );
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled( "(%s)", RealToString( thread ) );
|
||||
m_drawThreadMigrations = thread;
|
||||
m_cpuDataThread = thread;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( untracked )
|
||||
{
|
||||
TextFocused( "Program:", m_worker.GetCaptureProgram().c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
TextFocused( "Program:", txt );
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if( untracked )
|
||||
{
|
||||
TextDisabledUnformatted( "(untracked thread in profiled program)" );
|
||||
}
|
||||
else
|
||||
{
|
||||
TextDisabledUnformatted( "(external)" );
|
||||
}
|
||||
TextFocused( "Thread:", m_worker.GetExternalName( thread ).second );
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled( "(%s)", RealToString( thread ) );
|
||||
}
|
||||
ImGui::Separator();
|
||||
TextFocused( "Start time:", TimeToStringExact( start ) );
|
||||
TextFocused( "End time:", TimeToStringExact( end ) );
|
||||
TextFocused( "Activity time:", TimeToString( end - start ) );
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PushFont( m_smallFont );
|
||||
|
||||
if( local && IsMouseClicked( 0 ) )
|
||||
{
|
||||
auto& item = m_tc.GetItem( m_worker.GetThreadData( thread ) );
|
||||
item.SetVisible( true );
|
||||
item.SetShowFull( true );
|
||||
}
|
||||
if( IsMouseClicked( 2 ) )
|
||||
{
|
||||
ZoomToRange( start, end );
|
||||
}
|
||||
}
|
||||
++it;
|
||||
ZoomToRange( t0, t1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char buf[64];
|
||||
if( tt )
|
||||
{
|
||||
sprintf( buf, "[%i:%i] CPU %i", tt->package, tt->core, i );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buf, "CPU %i", i );
|
||||
}
|
||||
const auto txtx = ImGui::CalcTextSize( buf ).x;
|
||||
DrawTextSuperContrast( draw, wpos + ImVec2( ty, offset-1 ), 0xFFDD88DD, buf );
|
||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 0, offset-1 ), wpos + ImVec2( sty + txtx, offset + sty ) ) )
|
||||
{
|
||||
ImGui::PopFont();
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "CPU:", RealToString( i ) );
|
||||
if( tt )
|
||||
const auto end = ev.IsEndValid() ? ev.End() : m_worker.GetLastTime();
|
||||
const auto px1 = ( end - vStart ) * pxns;
|
||||
|
||||
const auto thread = m_worker.DecompressThreadExternal( ev.Thread() );
|
||||
bool local, untracked;
|
||||
const char* txt;
|
||||
auto label = GetThreadContextData( thread, local, untracked, txt );
|
||||
|
||||
uint32_t color;
|
||||
if( m_vd.dynamicColors != 0 )
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Package:", RealToString( tt->package ) );
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Core:", RealToString( tt->core ) );
|
||||
color = local ? GetThreadColor( thread, 0 ) : ( untracked ? 0xFF663333 : 0xFF444444 );
|
||||
}
|
||||
else
|
||||
{
|
||||
color = local ? 0xFF334488 : ( untracked ? 0xFF663333 : 0xFF444444 );
|
||||
}
|
||||
|
||||
draw->AddRectFilled( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + sty ), color );
|
||||
if( m_drawThreadHighlight == thread )
|
||||
{
|
||||
draw->AddRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + sty ), 0xFFFFFFFF );
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto accentColor = HighlightColor( color );
|
||||
const auto darkColor = DarkenColor( color );
|
||||
DrawLine( draw, dpos + ImVec2( px0, offset + sty ), dpos + ImVec2( px0, offset ), dpos + ImVec2( px1-1, offset ), accentColor, 1.f );
|
||||
DrawLine( draw, dpos + ImVec2( px0, offset + sty ), dpos + ImVec2( px1-1, offset + sty ), dpos + ImVec2( px1-1, offset ), darkColor, 1.f );
|
||||
}
|
||||
|
||||
const auto zsz = px1 - px0;
|
||||
auto tsz = ImGui::CalcTextSize( label );
|
||||
if( tsz.x < zsz )
|
||||
{
|
||||
const auto x = ( ev.Start() - m_vd.zvStart ) * pxns + ( ( end - ev.Start() ) * pxns - tsz.x ) / 2;
|
||||
if( x < 0 || x > w - tsz.x )
|
||||
{
|
||||
ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );
|
||||
DrawTextContrast( draw, wpos + ImVec2( std::max( std::max( 0., px0 ), std::min( double( w - tsz.x ), x ) ), offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
else if( ev.Start() == ev.End() )
|
||||
{
|
||||
DrawTextContrast( draw, wpos + ImVec2( px0 + ( px1 - px0 - tsz.x ) * 0.5, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTextContrast( draw, wpos + ImVec2( x, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::PushClipRect( wpos + ImVec2( px0, offset ), wpos + ImVec2( px1, offset + tsz.y * 2 ), true );
|
||||
DrawTextContrast( draw, wpos + ImVec2( ( ev.Start() - vStart ) * pxns, offset-1 ), local ? 0xFFFFFFFF : 0xAAFFFFFF, label );
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
|
||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( px0, offset-1 ), wpos + ImVec2( px1, offset + sty ) ) )
|
||||
{
|
||||
m_drawThreadHighlight = thread;
|
||||
ImGui::PopFont();
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "CPU:", RealToString( i ) );
|
||||
if( tt )
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Package:", RealToString( tt->package ) );
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Core:", RealToString( tt->core ) );
|
||||
}
|
||||
if( local )
|
||||
{
|
||||
TextFocused( "Program:", m_worker.GetCaptureProgram().c_str() );
|
||||
ImGui::SameLine();
|
||||
TextDisabledUnformatted( "(profiled program)" );
|
||||
SmallColorBox( GetThreadColor( thread, 0 ) );
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Thread:", m_worker.GetThreadName( thread ) );
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled( "(%s)", RealToString( thread ) );
|
||||
m_drawThreadMigrations = thread;
|
||||
m_cpuDataThread = thread;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( untracked )
|
||||
{
|
||||
TextFocused( "Program:", m_worker.GetCaptureProgram().c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
TextFocused( "Program:", txt );
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if( untracked )
|
||||
{
|
||||
TextDisabledUnformatted( "(untracked thread in profiled program)" );
|
||||
}
|
||||
else
|
||||
{
|
||||
TextDisabledUnformatted( "(external)" );
|
||||
}
|
||||
TextFocused( "Thread:", m_worker.GetExternalName( thread ).second );
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled( "(%s)", RealToString( thread ) );
|
||||
}
|
||||
ImGui::Separator();
|
||||
TextFocused( "Start time:", TimeToStringExact( ev.Start() ) );
|
||||
TextFocused( "End time:", TimeToStringExact( end ) );
|
||||
TextFocused( "Activity time:", TimeToString( end - ev.Start() ) );
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PushFont( m_smallFont );
|
||||
|
||||
if( local && IsMouseClicked( 0 ) )
|
||||
{
|
||||
auto& item = m_tc.GetItem( m_worker.GetThreadData( thread ) );
|
||||
item.SetVisible( true );
|
||||
item.SetShowFull( true );
|
||||
}
|
||||
if( IsMouseClicked( 2 ) )
|
||||
{
|
||||
ZoomToRange( ev.Start(), end );
|
||||
}
|
||||
}
|
||||
TextFocused( "Context switch regions:", RealToString( cs.size() ) );
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PushFont( m_smallFont );
|
||||
}
|
||||
}
|
||||
offset += sstep;
|
||||
}
|
||||
|
||||
char buf[64];
|
||||
if( tt )
|
||||
{
|
||||
sprintf( buf, "[%i:%i] CPU %i", tt->package, tt->core, i );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buf, "CPU %i", i );
|
||||
}
|
||||
const auto txtx = ImGui::CalcTextSize( buf ).x;
|
||||
DrawTextSuperContrast( draw, wpos + ImVec2( ty, offset-1 ), 0xFFDD88DD, buf );
|
||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 0, offset-1 ), wpos + ImVec2( sty + txtx, offset + sty ) ) )
|
||||
{
|
||||
ImGui::PopFont();
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "CPU:", RealToString( i ) );
|
||||
if( tt )
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Package:", RealToString( tt->package ) );
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Core:", RealToString( tt->core ) );
|
||||
}
|
||||
TextFocused( "Context switch regions:", RealToString( cpuData[i].cs.size() ) );
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PushFont( m_smallFont );
|
||||
}
|
||||
|
||||
offset += sstep;
|
||||
}
|
||||
|
||||
if( m_drawThreadMigrations != 0 )
|
||||
|
Loading…
Reference in New Issue
Block a user