mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-22 22: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;
|
int other;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct CpuCtxDraw
|
||||||
|
{
|
||||||
|
uint32_t idx;
|
||||||
|
uint32_t num;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -41,18 +41,20 @@ int64_t TimelineItemCpuData::RangeEnd() const
|
|||||||
|
|
||||||
bool TimelineItemCpuData::DrawContents( const TimelineContext& ctx, int& offset )
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineItemCpuData::DrawFinished()
|
void TimelineItemCpuData::DrawFinished()
|
||||||
{
|
{
|
||||||
m_cpuDraw.clear();
|
m_cpuDraw.clear();
|
||||||
|
for( auto& v : m_ctxDraw ) v.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineItemCpuData::Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible )
|
void TimelineItemCpuData::Preprocess( const TimelineContext& ctx, TaskDispatch& td, bool visible )
|
||||||
{
|
{
|
||||||
assert( m_cpuDraw.empty() );
|
assert( m_cpuDraw.empty() );
|
||||||
|
for( auto& v : m_ctxDraw ) assert( v.empty() );
|
||||||
|
|
||||||
if( !visible ) return;
|
if( !visible ) return;
|
||||||
|
|
||||||
@ -66,6 +68,65 @@ void TimelineItemCpuData::Preprocess( const TimelineContext& ctx, TaskDispatch&
|
|||||||
PreprocessCpuUsage( ctx );
|
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 )
|
void TimelineItemCpuData::PreprocessCpuUsage( const TimelineContext& ctx )
|
||||||
|
@ -34,8 +34,10 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void PreprocessCpuUsage( const TimelineContext& ctx );
|
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<CpuUsageDraw> m_cpuDraw;
|
||||||
|
std::vector<std::vector<CpuCtxDraw>> m_ctxDraw;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ struct ContextSwitchDraw;
|
|||||||
struct SamplesDraw;
|
struct SamplesDraw;
|
||||||
struct MessagesDraw;
|
struct MessagesDraw;
|
||||||
struct CpuUsageDraw;
|
struct CpuUsageDraw;
|
||||||
|
struct CpuCtxDraw;
|
||||||
|
|
||||||
class View
|
class View
|
||||||
{
|
{
|
||||||
@ -132,7 +133,7 @@ public:
|
|||||||
void DrawThreadMessagesList( const TimelineContext& ctx, const std::vector<MessagesDraw>& drawList, int offset, uint64_t tid );
|
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 );
|
void DrawThreadOverlays( const ThreadData& thread, const ImVec2& ul, const ImVec2& dr );
|
||||||
bool DrawGpu( const TimelineContext& ctx, const GpuCtxData& gpu, int& offset );
|
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;
|
bool m_showRanges = false;
|
||||||
Range m_statRange;
|
Range m_statRange;
|
||||||
|
@ -9,12 +9,12 @@
|
|||||||
#include "TracyTimelineContext.hpp"
|
#include "TracyTimelineContext.hpp"
|
||||||
#include "TracyView.hpp"
|
#include "TracyView.hpp"
|
||||||
|
|
||||||
|
constexpr float MinVisSize = 3;
|
||||||
|
|
||||||
namespace tracy
|
namespace tracy
|
||||||
{
|
{
|
||||||
|
|
||||||
constexpr float MinVisSize = 3;
|
bool View::DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDraw>& cpuDraw, const std::vector<std::vector<CpuCtxDraw>>& ctxDraw, int& offset )
|
||||||
|
|
||||||
bool View::DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDraw>& cpuDraw, int& offset )
|
|
||||||
{
|
{
|
||||||
auto cpuData = m_worker.GetCpuData();
|
auto cpuData = m_worker.GetCpuData();
|
||||||
const auto cpuCnt = m_worker.GetCpuDataCpuCount();
|
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 yMin = ctx.yMin;
|
||||||
const auto yMax = ctx.yMax;
|
const auto yMax = ctx.yMax;
|
||||||
const auto hover = ctx.hover;
|
const auto hover = ctx.hover;
|
||||||
|
const auto vStart = ctx.vStart;
|
||||||
|
|
||||||
auto draw = ImGui::GetWindowDrawList();
|
auto draw = ImGui::GetWindowDrawList();
|
||||||
|
|
||||||
@ -146,243 +147,215 @@ bool View::DrawCpuData( const TimelineContext& ctx, const std::vector<CpuUsageDr
|
|||||||
const auto origOffset = offset;
|
const auto origOffset = offset;
|
||||||
for( int i=0; i<cpuCnt; i++ )
|
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 );
|
const auto& ev = cs[v.idx];
|
||||||
|
const auto t0 = ev.Start();
|
||||||
auto& cs = cpuData[i].cs;
|
const auto px0 = ( t0 - vStart ) * pxns;
|
||||||
auto tt = m_worker.GetThreadTopology( i );
|
if( v.num > 0 )
|
||||||
|
|
||||||
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() )
|
|
||||||
{
|
{
|
||||||
auto eit = std::lower_bound( it, cs.end(), m_vd.zvEnd, [] ( const auto& l, const auto& r ) { return l.Start() < r; } );
|
const auto& eev = cs[v.idx + v.num - 1];
|
||||||
while( it < eit )
|
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();
|
ImGui::PopFont();
|
||||||
const auto end = it->End();
|
ImGui::BeginTooltip();
|
||||||
const auto zsz = std::max( ( end - start ) * pxns, pxns * 0.5 );
|
TextFocused( "CPU:", RealToString( i ) );
|
||||||
if( zsz < MinVisSize )
|
if( tt )
|
||||||
{
|
{
|
||||||
const auto MinVisNs = MinVisSize * nspx;
|
ImGui::SameLine();
|
||||||
int num = 0;
|
ImGui::Spacing();
|
||||||
const auto px0 = ( start - m_vd.zvStart ) * pxns;
|
ImGui::SameLine();
|
||||||
auto px1ns = end - m_vd.zvStart;
|
TextFocused( "Package:", RealToString( tt->package ) );
|
||||||
auto rend = end;
|
ImGui::SameLine();
|
||||||
auto nextTime = end + MinVisNs;
|
TextFocused( "Core:", RealToString( tt->core ) );
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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() );
|
ZoomToRange( t0, t1 );
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[64];
|
|
||||||
if( tt )
|
|
||||||
{
|
|
||||||
sprintf( buf, "[%i:%i] CPU %i", tt->package, tt->core, i );
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf( buf, "CPU %i", i );
|
const auto end = ev.IsEndValid() ? ev.End() : m_worker.GetLastTime();
|
||||||
}
|
const auto px1 = ( end - vStart ) * pxns;
|
||||||
const auto txtx = ImGui::CalcTextSize( buf ).x;
|
|
||||||
DrawTextSuperContrast( draw, wpos + ImVec2( ty, offset-1 ), 0xFFDD88DD, buf );
|
const auto thread = m_worker.DecompressThreadExternal( ev.Thread() );
|
||||||
if( hover && ImGui::IsMouseHoveringRect( wpos + ImVec2( 0, offset-1 ), wpos + ImVec2( sty + txtx, offset + sty ) ) )
|
bool local, untracked;
|
||||||
{
|
const char* txt;
|
||||||
ImGui::PopFont();
|
auto label = GetThreadContextData( thread, local, untracked, txt );
|
||||||
ImGui::BeginTooltip();
|
|
||||||
TextFocused( "CPU:", RealToString( i ) );
|
uint32_t color;
|
||||||
if( tt )
|
if( m_vd.dynamicColors != 0 )
|
||||||
{
|
{
|
||||||
ImGui::SameLine();
|
color = local ? GetThreadColor( thread, 0 ) : ( untracked ? 0xFF663333 : 0xFF444444 );
|
||||||
ImGui::Spacing();
|
}
|
||||||
ImGui::SameLine();
|
else
|
||||||
TextFocused( "Package:", RealToString( tt->package ) );
|
{
|
||||||
ImGui::SameLine();
|
color = local ? 0xFF334488 : ( untracked ? 0xFF663333 : 0xFF444444 );
|
||||||
TextFocused( "Core:", RealToString( tt->core ) );
|
}
|
||||||
|
|
||||||
|
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 )
|
if( m_drawThreadMigrations != 0 )
|
||||||
|
Loading…
Reference in New Issue
Block a user