1
0
mirror of https://github.com/wolfpld/tracy.git synced 2025-03-20 07:40:02 +08:00

Display hardware counter statistics in asm line columns.

This commit is contained in:
Bartosz Taudul 2021-05-23 02:39:31 +02:00
parent 77c33327f4
commit 815cf7d00a
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3
2 changed files with 173 additions and 4 deletions

View File

@ -89,6 +89,7 @@ SourceView::SourceView( ImFont* font, GetWindowCallback gwcb )
, m_calcInlineStats( true )
, m_atnt( false )
, m_childCalls( false )
, m_hwSamples( true )
, m_showJumps( true )
, m_cpuArch( CpuArchUnknown )
, m_showLatency( false )
@ -1135,6 +1136,13 @@ void SourceView::RenderSymbolView( const Worker& worker, View& view )
{
m_childCalls = !m_childCalls;
}
if( worker.GetHwSampleCountAddress() != 0 )
{
SmallCheckbox( ICON_FA_HAND_POINT_DOWN " Hardware samples", &m_hwSamples );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
}
SmallCheckbox( ICON_FA_SIGN_OUT_ALT " Child calls", &m_childCalls );
if( !slzReady )
{
@ -1963,7 +1971,12 @@ uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unorder
const auto ts = ImGui::CalcTextSize( " " );
const auto th2 = floor( ts.y / 2 );
const auto th4 = floor( ts.y / 4 );
const auto xoff = ( ( iptotal.local + iptotal.ext ) == 0 ? 0 : ( 7 * ts.x + ts.y ) ) + (3+maxAddrLen) * ts.x + ( ( m_asmShowSourceLocation && !m_sourceFiles.empty() ) ? 36 * ts.x : 0 ) + ( m_asmBytes ? m_maxAsmBytes*3 * ts.x : 0 );
const auto xoff =
( ( iptotal.local + iptotal.ext ) == 0 ? 0 : ( 7 * ts.x + ts.y ) ) +
(3+maxAddrLen) * ts.x +
( ( m_asmShowSourceLocation && !m_sourceFiles.empty() ) ? 36 * ts.x : 0 ) +
( m_asmBytes ? m_maxAsmBytes*3 * ts.x : 0 ) +
( ( m_hwSamples && worker.GetHwSampleCountAddress() != 0 ) ? ( 19 * ts.x + ts.y ) : 0 );
const auto minAddr = m_asm[clipper.DisplayStart].addr;
const auto maxAddr = m_asm[clipper.DisplayEnd-1].addr;
const auto mjl = m_maxJumpLevel;
@ -2632,11 +2645,11 @@ void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const Addr
const auto asmIdx = &line - m_asm.data();
const auto ts = ImGui::CalcTextSize( " " );
if( iptotal.local + iptotal.ext != 0 )
{
if( ( m_childCalls && ipcnt.local + ipcnt.ext == 0 ) || ( !m_childCalls && ipcnt.local == 0 ) )
{
const auto ts = ImGui::CalcTextSize( " " );
ImGui::ItemSize( ImVec2( 7 * ts.x, ts.y ) );
if( ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect( wpos, wpos + ImVec2( ts.x * 7, ty ) ) )
{
@ -2784,6 +2797,157 @@ void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const Addr
ImGui::SameLine( 0, ty );
}
const bool showHwSamples = m_hwSamples && worker.GetHwSampleCountAddress() != 0;
if( showHwSamples )
{
auto hw = worker.GetHwSampleData( line.addr );
if( hw )
{
if( hw->cycles != 0 )
{
const bool unreliable = hw->cycles < 10 || hw->retired < 10;
const float ipc = float( hw->retired ) / hw->cycles;
uint32_t col = unreliable ? 0x66FFFFFF : 0xFFFFFFFF;
if( ipc >= 10 )
{
TextColoredUnformatted( col, " 10+ " );
}
else
{
char buf[16];
*buf = ' ';
const auto end = PrintFloat( buf+1, buf+16, ipc, 2 );
assert( end == buf + 5 );
memcpy( end, " ", 3 );
TextColoredUnformatted( col, buf );
}
if( ImGui::IsItemHovered() )
{
if( m_font ) ImGui::PopFont();
ImGui::BeginTooltip();
ImGui::TextUnformatted( "Instructions Per Cycle (IPC)" );
ImGui::SameLine();
TextDisabledUnformatted( "Higher is better" );
ImGui::Separator();
TextFocused( "Cycles:", RealToString( hw->cycles ) );
TextFocused( "Retirements:", RealToString( hw->retired ) );
if( unreliable ) TextColoredUnformatted( 0xFF4444FF, "Not enough samples for reliable data!" );
ImGui::EndTooltip();
if( m_font ) ImGui::PushFont( m_font );
}
}
else
{
ImGui::ItemSize( ImVec2( 7 * ts.x, ts.y ) );
}
ImGui::SameLine( 0, 0 );
if( hw->branchRetired != 0 )
{
const bool unreliable = hw->branchRetired < 10;
const float rate = float( hw->branchMiss ) / hw->branchRetired;
uint32_t col = unreliable ? 0x66FFFFFF : 0xFFFFFFFF;
if( hw->branchMiss == 0 )
{
TextColoredUnformatted( col, " 0% " );
}
else if( rate >= 1.f )
{
TextColoredUnformatted( col, " 100% " );
}
else
{
char buf[16];
if( rate >= 0.1f )
{
const auto end = PrintFloat( buf, buf+16, rate * 100, 1 );
assert( end == buf+4 );
}
else
{
*buf = ' ';
const auto end = PrintFloat( buf+1, buf+16, rate * 100, 1 );
assert( end == buf+4 );
}
memcpy( buf+4, "% ", 4 );
TextColoredUnformatted( col, buf );
}
if( ImGui::IsItemHovered() )
{
if( m_font ) ImGui::PopFont();
ImGui::BeginTooltip();
ImGui::TextUnformatted( "Branch mispredictions rate" );
ImGui::SameLine();
TextDisabledUnformatted( "Lower is better" );
ImGui::Separator();
TextFocused( "Retired branches:", RealToString( hw->branchRetired ) );
TextFocused( "Branch mispredictions:", RealToString( hw->branchMiss ) );
if( unreliable ) TextColoredUnformatted( 0xFF4444FF, "Not enough samples for reliable data!" );
ImGui::EndTooltip();
if( m_font ) ImGui::PushFont( m_font );
}
}
else
{
ImGui::ItemSize( ImVec2( 7 * ts.x, ts.y ) );
}
ImGui::SameLine( 0, 0 );
if( hw->cacheRef != 0 )
{
const bool unreliable = hw->cacheRef < 10;
const float rate = float( hw->cacheMiss ) / hw->cacheRef;
uint32_t col = unreliable ? 0xFF888888 : 0xFFFFFFFF;
if( hw->cacheMiss == 0 )
{
TextColoredUnformatted( col, " 0%" );
}
else if( rate >= 1.f )
{
TextColoredUnformatted( col, " 100%" );
}
else
{
char buf[16];
if( rate >= 0.1f )
{
const auto end = PrintFloat( buf, buf+16, rate * 100, 1 );
assert( end == buf+4 );
}
else
{
*buf = ' ';
const auto end = PrintFloat( buf+1, buf+16, rate * 100, 1 );
assert( end == buf+4 );
}
memcpy( buf+4, "%", 2 );
TextColoredUnformatted( col, buf );
}
if( ImGui::IsItemHovered() )
{
if( m_font ) ImGui::PopFont();
ImGui::BeginTooltip();
ImGui::TextUnformatted( "Cache miss rate" );
ImGui::SameLine();
TextDisabledUnformatted( "Lower is better" );
ImGui::Separator();
TextFocused( "Cache references:", RealToString( hw->cacheRef ) );
TextFocused( "Cache misses:", RealToString( hw->cacheMiss ) );
if( unreliable ) TextColoredUnformatted( 0xFF4444FF, "Not enough samples for reliable data!" );
ImGui::EndTooltip();
if( m_font ) ImGui::PushFont( m_font );
}
}
else
{
ImGui::ItemSize( ImVec2( 5 * ts.x, ts.y ) );
}
}
else
{
ImGui::ItemSize( ImVec2( 19 * ts.x, ts.y ) );
}
ImGui::SameLine( 0, ty );
}
char buf[256];
if( m_asmCountBase >= 0 )
{
@ -2990,12 +3154,16 @@ void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const Addr
auto jit = m_jumpOut.find( line.addr );
if( jit != m_jumpOut.end() )
{
const auto ts = ImGui::CalcTextSize( " " );
const auto th2 = floor( ts.y / 2 );
const auto th4 = floor( ts.y / 4 );
const auto& mjl = m_maxJumpLevel;
const auto col = GetHsvColor( line.jumpAddr, 6 );
const auto xoff = ( ( iptotal.local + iptotal.ext == 0 ) ? 0 : ( 7 * ts.x + ts.y ) ) + (3+maxAddrLen) * ts.x + ( ( m_asmShowSourceLocation && !m_sourceFiles.empty() ) ? 36 * ts.x : 0 ) + ( m_asmBytes ? m_maxAsmBytes*3 * ts.x : 0 );
const auto xoff =
( ( iptotal.local + iptotal.ext == 0 ) ? 0 : ( 7 * ts.x + ts.y ) ) +
(3+maxAddrLen) * ts.x +
( ( m_asmShowSourceLocation && !m_sourceFiles.empty() ) ? 36 * ts.x : 0 ) +
( m_asmBytes ? m_maxAsmBytes*3 * ts.x : 0 ) +
( showHwSamples ? ( 19 * ts.x + ts.y ) : 0 );
DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * mjl + th2, th2 ), dpos + ImVec2( xoff + JumpSeparation * mjl + th2 + JumpArrow / 2, th2 ), col );
DrawLine( draw, dpos + ImVec2( xoff + JumpSeparation * mjl + th2, th2 ), dpos + ImVec2( xoff + JumpSeparation * mjl + th2 + th4, th2 - th4 ), col );

View File

@ -183,6 +183,7 @@ private:
uint8_t m_maxAsmBytes;
bool m_atnt;
uint64_t m_jumpPopupAddr;
bool m_hwSamples;
bool m_childCalls;
SourceContents m_source;