1
0
mirror of https://github.com/wolfpld/tracy synced 2025-04-29 04:23:51 +00:00

Compare commits

..

No commits in common. "4a1142fddf27aac608f12a325e490b6fa71bf05e" and "d71d76414b8cc6a3d5658ceed57e540687d1c23e" have entirely different histories.

9 changed files with 117 additions and 484 deletions

1
NEWS
View File

@ -12,7 +12,6 @@ v0.x.x (xxxx-xx-xx)
- Updated Zen 3 and added Tiger Lake microarchitectural data.
- Manually disconnecting from the server will no longer display erroneous
warning message.
- Added ability to display sample time spent in child function calls.
v0.7.7 (2021-04-01)

View File

@ -512,7 +512,7 @@ LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const si
/*-************************************
* Common functions
**************************************/
LZ4_FORCE_INLINE unsigned LZ4_NbCommonBytes (reg_t val)
static unsigned LZ4_NbCommonBytes (reg_t val)
{
assert(val != 0);
if (LZ4_isLittleEndian()) {

View File

@ -3244,8 +3244,6 @@ An assembly instruction may be associated with only a single source line, but a
If automated call stack sampling (see chapter~\ref{sampling}) was performed, additional profiling information will be available. The first column of source and assembly views will contain percentage counts of collected instruction pointer samples for each displayed line, both in numerical and graphical bar form. This information can be used to determine which line of the function takes the most time. The displayed percentage values are heat map color coded, with the lowest values mapped to dark red, and the highest values mapped to bright yellow. The color code will appear next to the percentage value, and on the scroll bar, so that 'hot' places in code can be identified at a glance.
By default samples are displayed only from within the selected symbol, in isolation. In some cases you may however want to include samples from functions that were called. To do so, enable the \emph{\faSignOut*{}~Child calls} option, which may also be temporarily toggled by pressing the \keys{Z} key. Make sure to familiarize yourself with section~\ref{readingcallstacks} to be able to properly read the results.
Instruction timings can be viewed as a group. To begin constructing such group, click the \LMB{}~left mouse button on the percentage value. Additional instructions can be added using the \keys{\ctrl}~key, while holding the \keys{\shift}~key will allow selection of a range. To cancel the selection, click the \RMB{}~right mouse button on a percentage value. Group statistics can be seen at the bottom of the pane.
Clicking the \MMB{}~middle mouse button on the percentage value of an assembly instruction will display entry call stacks of the selected sample (see chapter~\ref{sampleparents}). This functionality is only available for instructions that have collected sampling data, and only in the assembly view, as the source code may be inlined multiple times, which would result in ambiguous location data. Note that number of entry call stacks is displayed in a tooltip, for a quick reference.

View File

@ -124,7 +124,7 @@ std::vector<Tokenizer::Token> Tokenizer::Tokenize( const char* begin, const char
}
else
{
while( begin != end && isspace( (uint8_t)*begin ) ) begin++;
while( begin != end && isspace( *begin ) ) begin++;
if( first && begin < end && *begin == '#' )
{
if( *(end-1) == '\\' ) m_isInPreprocessor = true;

View File

@ -88,7 +88,6 @@ SourceView::SourceView( ImFont* font, GetWindowCallback gwcb )
, m_asmShowSourceLocation( true )
, m_calcInlineStats( true )
, m_atnt( false )
, m_childCalls( false )
, m_showJumps( true )
, m_cpuArch( CpuArchUnknown )
, m_showLatency( false )
@ -864,7 +863,6 @@ void SourceView::RenderSimpleSourceView()
const auto lx = ts * maxLine + ty + round( ts*0.4f );
draw->AddLine( wpos + ImVec2( lx, 0 ), wpos + ImVec2( lx, wh ), 0x08FFFFFF );
const AddrStat zero = {};
if( m_targetLine != 0 )
{
int lineNum = 1;
@ -875,7 +873,7 @@ void SourceView::RenderSimpleSourceView()
m_targetLine = 0;
ImGui::SetScrollHereY();
}
RenderLine( line, lineNum++, zero, zero, zero, nullptr );
RenderLine( line, lineNum++, 0, 0, 0, nullptr );
}
const auto win = ImGui::GetCurrentWindowRead();
m_srcWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;
@ -888,7 +886,7 @@ void SourceView::RenderSimpleSourceView()
{
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
{
RenderLine( lines[i], i+1, zero, zero, zero, nullptr );
RenderLine( lines[i], i+1, 0, 0, 0, nullptr );
}
}
}
@ -1094,13 +1092,12 @@ void SourceView::RenderSymbolView( const Worker& worker, View& view )
TextFocused( ICON_FA_WEIGHT_HANGING " Code size:", MemSizeToString( m_codeLen ) );
}
AddrStat iptotalSrc = {}, iptotalAsm = {};
AddrStat ipmaxSrc = {}, ipmaxAsm = {};
unordered_flat_map<uint64_t, AddrStat> ipcountSrc, ipcountAsm;
uint32_t iptotalSrc = 0, iptotalAsm = 0;
uint32_t ipmaxSrc = 0, ipmaxAsm = 0;
unordered_flat_map<uint64_t, uint32_t> ipcountSrc, ipcountAsm;
if( m_calcInlineStats )
{
GatherIpStats( m_symAddr, iptotalSrc, iptotalAsm, ipcountSrc, ipcountAsm, ipmaxSrc, ipmaxAsm, worker, limitView, view );
GatherAdditionalIpStats( m_symAddr, iptotalSrc, iptotalAsm, ipcountSrc, ipcountAsm, ipmaxSrc, ipmaxAsm, worker, limitView, view );
}
else
{
@ -1115,78 +1112,18 @@ void SourceView::RenderSymbolView( const Worker& worker, View& view )
iptr++;
}
}
GatherAdditionalIpStats( m_symAddr, iptotalSrc, iptotalAsm, ipcountSrc, ipcountAsm, ipmaxSrc, ipmaxAsm, worker, limitView, view );
iptotalSrc = iptotalAsm;
}
const auto slzReady = worker.AreSourceLocationZonesReady();
if( ( iptotalAsm.local + iptotalAsm.ext ) > 0 || ( view.m_statRange.active && worker.GetSamplesForSymbol( m_baseAddr ) ) )
if( iptotalAsm > 0 )
{
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
if( !slzReady )
{
ImGui::PushItemFlag( ImGuiItemFlags_Disabled, true );
ImGui::PushStyleVar( ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f );
m_childCalls = false;
}
else if( ImGui::IsKeyDown( 'Z' ) )
{
m_childCalls = !m_childCalls;
}
SmallCheckbox( ICON_FA_SIGN_OUT_ALT " Child calls", &m_childCalls );
if( !slzReady )
{
ImGui::PopStyleVar();
ImGui::PopItemFlag();
if( ImGui::IsItemHovered() )
{
ImGui::BeginTooltip();
ImGui::TextUnformatted( "Please wait, processing data..." );
ImGui::EndTooltip();
}
}
else
{
if( ImGui::IsItemHovered() )
{
ImGui::BeginTooltip();
ImGui::TextUnformatted( "Press Z key to temporarily reverse selection." );
ImGui::EndTooltip();
}
}
TextFocused( ICON_FA_STOPWATCH " Time:", TimeToString( iptotalAsm * worker.GetSamplingPeriod() ) );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
if( m_childCalls )
{
TextFocused( ICON_FA_STOPWATCH " Time:", TimeToString( ( iptotalAsm.local + iptotalAsm.ext ) * worker.GetSamplingPeriod() ) );
}
else
{
TextFocused( ICON_FA_STOPWATCH " Time:", TimeToString( iptotalAsm.local * worker.GetSamplingPeriod() ) );
}
if( iptotalAsm.ext )
{
ImGui::SameLine();
ImGui::TextDisabled( "(%c%s)", m_childCalls ? '-' : '+', TimeToString( iptotalAsm.ext * worker.GetSamplingPeriod() ) );
}
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
if( m_childCalls )
{
TextFocused( ICON_FA_EYE_DROPPER " Samples:", RealToString( iptotalAsm.local + iptotalAsm.ext ) );
}
else
{
TextFocused( ICON_FA_EYE_DROPPER " Samples:", RealToString( iptotalAsm.local ) );
}
if( iptotalAsm.ext )
{
ImGui::SameLine();
ImGui::Text( "(%c%s)", m_childCalls ? '-' : '+', RealToString( iptotalAsm.ext ) );
}
TextFocused( ICON_FA_EYE_DROPPER " Samples:", RealToString( iptotalAsm ) );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
@ -1202,7 +1139,7 @@ void SourceView::RenderSymbolView( const Worker& worker, View& view )
if( ImGui::IsItemHovered() )
{
ImGui::BeginTooltip();
ImGui::TextUnformatted( "Please wait, processing data..." );
ImGui::TextUnformatted( "Waiting for background tasks to finish" );
ImGui::EndTooltip();
}
}
@ -1251,8 +1188,6 @@ void SourceView::RenderSymbolView( const Worker& worker, View& view )
break;
}
if( slzReady && ImGui::IsKeyDown( 'Z' ) ) m_childCalls = !m_childCalls;
if( jumpOut != 0 )
{
auto sym = worker.GetSymbolData( jumpOut );
@ -1295,9 +1230,10 @@ static uint32_t GetHotnessColor( uint32_t ipSum, uint32_t maxIpCount )
{
return 0xFFFFFFFF;
}
}
void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordered_flat_map<uint64_t, AddrStat>& ipcount, const unordered_flat_map<uint64_t, AddrStat>& ipcountAsm, const AddrStat& ipmax, const Worker& worker, const View& view )
void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<uint64_t, uint32_t> ipcount, unordered_flat_map<uint64_t, uint32_t> ipcountAsm, uint32_t ipmax, const Worker& worker, const View& view )
{
if( m_sourceFiles.empty() )
{
@ -1379,15 +1315,15 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
}
else
{
AddrStat totalSamples = {};
unordered_flat_map<uint32_t, AddrStat> fileCounts;
uint32_t totalSamples = 0;
unordered_flat_map<uint32_t, uint32_t> fileCounts;
for( auto& v : m_asm )
{
uint32_t srcline;
const auto srcidx = worker.GetLocationForAddress( v.addr, srcline );
if( srcline != 0 )
{
AddrStat cnt = {};
uint32_t cnt = 0;
auto ait = ipcountAsm.find( v.addr );
if( ait != ipcountAsm.end() ) cnt = ait->second;
@ -1396,27 +1332,19 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
{
fileCounts.emplace( srcidx.Idx(), cnt );
}
else
else if( cnt != 0 )
{
fit->second += cnt;
}
totalSamples += cnt;
}
}
std::vector<std::pair<uint32_t, AddrStat>> fileCountsVec;
std::vector<std::pair<uint32_t, uint32_t>> fileCountsVec;
fileCountsVec.reserve( fileCounts.size() );
for( auto& v : fileCounts ) fileCountsVec.emplace_back( v.first, v.second );
if( m_childCalls )
{
pdqsort_branchless( fileCountsVec.begin(), fileCountsVec.end(), [&worker] (const auto& l, const auto& r ) { return ( l.second.local + l.second.ext == r.second.local + r.second.ext ) ? strcmp( worker.GetString( l.first ), worker.GetString( r.first ) ) < 0 : ( l.second.local + l.second.ext > r.second.local + r.second.ext ); } );
}
else
{
pdqsort_branchless( fileCountsVec.begin(), fileCountsVec.end(), [&worker] (const auto& l, const auto& r ) { return l.second.local == r.second.local ? strcmp( worker.GetString( l.first ), worker.GetString( r.first ) ) < 0 : l.second.local > r.second.local; } );
}
pdqsort_branchless( fileCountsVec.begin(), fileCountsVec.end(), [&worker] (const auto& l, const auto& r ) { return l.second == r.second ? strcmp( worker.GetString( l.first ), worker.GetString( r.first ) ) < 0 : l.second > r.second; } );
const auto hasSamples = totalSamples.local + totalSamples.ext != 0;
if( hasSamples )
if( totalSamples != 0 )
{
ImGui::Columns( 2 );
static bool widthSet = false;
@ -1431,48 +1359,21 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
}
for( auto& v : fileCountsVec )
{
if( hasSamples )
if( totalSamples != 0 )
{
auto fit = fileCounts.find( v.first );
assert( fit != fileCounts.end() );
if( fit->second.local + fit->second.ext != 0 )
if( fit->second != 0 )
{
if( m_childCalls )
{
ImGui::TextUnformatted( TimeToString( ( fit->second.local + fit->second.ext ) * worker.GetSamplingPeriod() ) );
}
else
{
ImGui::TextUnformatted( TimeToString( fit->second.local * worker.GetSamplingPeriod() ) );
}
ImGui::TextUnformatted( TimeToString( fit->second * worker.GetSamplingPeriod() ) );
ImGui::SameLine();
ImGui::TextDisabled( "(%.2f%%)", 100.f * fit->second / totalSamples );
if( ImGui::IsItemHovered() )
{
ImGui::BeginTooltip();
if( fit->second.local )
{
TextFocused( "Local time:", TimeToString( fit->second.local * worker.GetSamplingPeriod() ) );
TextFocused( "Local samples:", RealToString( fit->second.local ) );
}
if( fit->second.ext )
{
TextFocused( "Child time:", TimeToString( fit->second.ext * worker.GetSamplingPeriod() ) );
TextFocused( "Child samples:", RealToString( fit->second.ext ) );
}
TextFocused( "Sample count:", RealToString( fit->second ) );
ImGui::EndTooltip();
}
ImGui::SameLine();
if( m_childCalls )
{
ImGui::TextDisabled( "(%.2f%%)", 100.f * ( fit->second.local + fit->second.ext ) / ( totalSamples.local + totalSamples.ext ) );
}
else if( totalSamples.local != 0 )
{
ImGui::TextDisabled( "(%.2f%%)", 100.f * fit->second.local / totalSamples.local );
}
else
{
ImGui::TextDisabled( "(%.2f%%)", 0 );
}
}
ImGui::NextColumn();
}
@ -1504,9 +1405,9 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
{
TextDisabledUnformatted( fstr );
}
if( hasSamples ) ImGui::NextColumn();
if( totalSamples != 0 ) ImGui::NextColumn();
}
if( hasSamples ) ImGui::EndColumns();
if( totalSamples != 0 ) ImGui::EndColumns();
}
ImGui::EndCombo();
}
@ -1528,7 +1429,7 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
const auto tmp = RealToString( lineCount );
const auto maxLine = strlen( tmp );
auto lx = ts * maxLine + ty + round( ts*0.4f );
if( iptotal.local + iptotal.ext != 0 ) lx += ts * 7 + ty;
if( iptotal != 0 ) lx += ts * 7 + ty;
if( !m_asm.empty() )
{
const auto tmp = RealToString( m_asm.size() );
@ -1537,7 +1438,6 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
}
draw->AddLine( wpos + ImVec2( lx, 0 ), wpos + ImVec2( lx, wh ), 0x08FFFFFF );
const AddrStat zero = {};
m_selectedAddressesHover.clear();
if( m_targetLine != 0 )
{
@ -1549,7 +1449,7 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
m_targetLine = 0;
ImGui::SetScrollHereY();
}
RenderLine( line, lineNum++, zero, iptotal, ipmax, &worker );
RenderLine( line, lineNum++, 0, iptotal, ipmax, &worker );
}
const auto win = ImGui::GetCurrentWindowRead();
m_srcWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;
@ -1560,11 +1460,11 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
clipper.Begin( (int)lines.size() );
while( clipper.Step() )
{
if( iptotal.local + iptotal.ext == 0 )
if( iptotal == 0 )
{
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
{
RenderLine( lines[i], i+1, zero, zero, zero, &worker );
RenderLine( lines[i], i+1, 0, 0, 0, &worker );
}
}
else
@ -1572,7 +1472,7 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
{
auto it = ipcount.find( i+1 );
const auto ipcnt = it == ipcount.end() ? zero : it->second;
const auto ipcnt = it == ipcount.end() ? 0 : it->second;
RenderLine( lines[i], i+1, ipcnt, iptotal, ipmax, &worker );
}
}
@ -1596,7 +1496,7 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
draw->AddLine( ImVec2( rect.Min.x, ly ), ImVec2( rect.Max.x, ly ), 0x88888888, 3 );
}
std::vector<std::pair<uint64_t, AddrStat>> ipData;
std::vector<std::pair<uint64_t, uint32_t>> ipData;
ipData.reserve( ipcount.size() );
for( auto& v : ipcount ) ipData.emplace_back( v.first, v.second );
for( uint32_t lineNum = 1; lineNum <= lines.size(); lineNum++ )
@ -1610,7 +1510,7 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
{
if( addr >= m_baseAddr && addr < m_baseAddr + m_codeLen )
{
ipData.emplace_back( lineNum, AddrStat {} );
ipData.emplace_back( lineNum, 0 );
break;
}
}
@ -1627,23 +1527,15 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
while( it != ipData.end() )
{
const auto firstLine = it->first;
AddrStat ipSum = {};
uint32_t ipSum = 0;
while( it != ipData.end() && it->first <= firstLine + step )
{
ipSum += it->second;
++it;
}
const auto ly = round( rect.Min.y + float( firstLine ) / lines.size() * rect.GetHeight() );
if( m_childCalls )
{
const auto color = ( ipSum.local + ipSum.ext == 0 ) ? 0x22FFFFFF : GetHotnessColor( ipSum.local + ipSum.ext, ipmax.local + ipmax.ext );
draw->AddRectFilled( ImVec2( x14, ly ), ImVec2( x34, ly+3 ), color );
}
else
{
const auto color = ipSum.local == 0 ? 0x22FFFFFF : GetHotnessColor( ipSum.local, ipmax.local );
draw->AddRectFilled( ImVec2( x14, ly ), ImVec2( x34, ly+3 ), color );
}
const uint32_t color = ipSum == 0 ? 0x22FFFFFF : GetHotnessColor( ipSum, ipmax );
draw->AddRectFilled( ImVec2( x14, ly ), ImVec2( x34, ly+3 ), color );
}
ImGui::PopClipRect();
@ -1654,7 +1546,7 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
if( !m_srcSampleSelect.empty() )
{
AddrStat count = {};
uint32_t count = 0;
uint32_t numLines = 0;
for( auto& idx : m_srcSampleSelect )
{
@ -1674,43 +1566,17 @@ void SourceView::RenderSymbolSourceView( const AddrStat& iptotal, const unordere
}
ImGui::SameLine();
char buf[16];
char* end;
if( m_childCalls )
{
end = PrintFloat( buf, buf+16, 100.f * ( count.local + count.ext ) / ( iptotal.local + iptotal.ext ), 2 );
}
else if( iptotal.local != 0 )
{
end = PrintFloat( buf, buf+16, 100.f * count.local / iptotal.local, 2 );
}
else
{
end = PrintFloat( buf, buf+16, 0.f, 2 );
}
auto end = PrintFloat( buf, buf+16, 100.f * count / iptotal, 2 );
memcpy( end, "%", 2 );
TextFocused( "Selected:", buf );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
if( m_childCalls )
{
TextFocused( "Time:", TimeToString( ( count.local + count.ext ) * worker.GetSamplingPeriod() ) );
}
else
{
TextFocused( "Time:", TimeToString( count.local * worker.GetSamplingPeriod() ) );
}
TextFocused( "Time:", TimeToString( count * worker.GetSamplingPeriod() ) );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
if( m_childCalls )
{
TextFocused( "Sample count:", RealToString( count.local + count.ext ) );
}
else
{
TextFocused( "Sample count:", RealToString( count.local ) );
}
TextFocused( "Sample count:", RealToString( count ) );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
@ -1766,7 +1632,7 @@ static int PrintHexBytes( char* buf, const uint8_t* bytes, size_t len, CpuArchit
}
}
uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unordered_flat_map<uint64_t, AddrStat>& ipcount, const AddrStat& ipmax, const Worker& worker, View& view )
uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<uint64_t, uint32_t> ipcount, uint32_t ipmax, const Worker& worker, View& view )
{
if( m_disasmFail >= 0 )
{
@ -1909,7 +1775,6 @@ uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unorder
uint64_t selJumpTarget;
uint64_t jumpOut = 0;
const AddrStat zero = {};
if( m_targetAddr != 0 )
{
for( auto& line : m_asm )
@ -1919,7 +1784,7 @@ uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unorder
m_targetAddr = 0;
ImGui::SetScrollHereY();
}
RenderAsmLine( line, zero, iptotal, ipmax, worker, jumpOut, maxAddrLen, view );
RenderAsmLine( line, 0, iptotal, ipmax, worker, jumpOut, maxAddrLen, view );
}
const auto win = ImGui::GetCurrentWindowRead();
m_asmWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;
@ -1935,11 +1800,11 @@ uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unorder
const auto wpos = ImGui::GetCursorScreenPos();
static std::vector<uint64_t> insList;
insList.clear();
if( iptotal.local + iptotal.ext == 0 )
if( iptotal == 0 )
{
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
{
RenderAsmLine( m_asm[i], zero, zero, zero, worker, jumpOut, maxAddrLen, view );
RenderAsmLine( m_asm[i], 0, 0, 0, worker, jumpOut, maxAddrLen, view );
insList.emplace_back( m_asm[i].addr );
}
}
@ -1949,7 +1814,7 @@ uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unorder
{
auto& line = m_asm[i];
auto it = ipcount.find( line.addr );
const auto ipcnt = it == ipcount.end() ? zero : it->second;
const auto ipcnt = it == ipcount.end() ? 0 : it->second;
RenderAsmLine( line, ipcnt, iptotal, ipmax, worker, jumpOut, maxAddrLen, view );
insList.emplace_back( line.addr );
}
@ -1960,7 +1825,7 @@ 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 == 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 minAddr = m_asm[clipper.DisplayStart].addr;
const auto maxAddr = m_asm[clipper.DisplayEnd-1].addr;
const auto mjl = m_maxJumpLevel;
@ -2143,7 +2008,7 @@ uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unorder
}
uint32_t selJumpLineStart, selJumpLineEnd, selJumpLineTarget;
std::vector<std::pair<uint64_t, AddrStat>> ipData;
std::vector<std::pair<uint64_t, uint32_t>> ipData;
ipData.reserve( ipcount.size() );
if( selJumpStart == 0 )
{
@ -2177,23 +2042,15 @@ uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unorder
while( it != ipData.end() )
{
const auto firstLine = it->first;
AddrStat ipSum = {};
uint32_t ipSum = 0;
while( it != ipData.end() && it->first <= firstLine + step )
{
ipSum += it->second;
++it;
}
const auto ly = round( rect.Min.y + float( firstLine ) / m_asm.size() * rect.GetHeight() );
if( m_childCalls )
{
const auto color = GetHotnessColor( ipSum.local + ipSum.ext, ipmax.local + ipmax.ext );
draw->AddRectFilled( ImVec2( x40, ly ), ImVec2( x60, ly+3 ), color );
}
else if( ipmax.local != 0 )
{
const auto color = GetHotnessColor( ipSum.local, ipmax.local );
draw->AddRectFilled( ImVec2( x40, ly ), ImVec2( x60, ly+3 ), color );
}
const uint32_t color = GetHotnessColor( ipSum, ipmax );
draw->AddRectFilled( ImVec2( x40, ly ), ImVec2( x60, ly+3 ), color );
}
if( selJumpStart != 0 )
@ -2249,7 +2106,7 @@ uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unorder
if( !m_asmSampleSelect.empty() )
{
AddrStat count = {};
uint32_t count = 0;
uint32_t numLines = 0;
for( auto& idx : m_asmSampleSelect )
{
@ -2269,43 +2126,17 @@ uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unorder
}
ImGui::SameLine();
char buf[16];
char* end;
if( m_childCalls )
{
end = PrintFloat( buf, buf+16, 100.f * ( count.local + count.ext ) / ( iptotal.local + iptotal.ext ), 2 );
}
else if( iptotal.local != 0 )
{
end = PrintFloat( buf, buf+16, 100.f * count.local / iptotal.local, 2 );
}
else
{
end = PrintFloat( buf, buf+16, 0.f, 2 );
}
auto end = PrintFloat( buf, buf+16, 100.f * count / iptotal, 2 );
memcpy( end, "%", 2 );
TextFocused( "Selected:", buf );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
if( m_childCalls )
{
TextFocused( "Time:", TimeToString( ( count.local + count.ext ) * worker.GetSamplingPeriod() ) );
}
else
{
TextFocused( "Time:", TimeToString( count.local * worker.GetSamplingPeriod() ) );
}
TextFocused( "Time:", TimeToString( count * worker.GetSamplingPeriod() ) );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
if( m_childCalls )
{
TextFocused( "Sample count:", RealToString( count.local + count.ext ) );
}
else
{
TextFocused( "Sample count:", RealToString( count.local ) );
}
TextFocused( "Sample count:", RealToString( count ) );
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
@ -2341,7 +2172,7 @@ static bool PrintPercentage( float val, uint32_t col = 0xFFFFFFFF )
return ImGui::IsWindowHovered() && ImGui::IsMouseHoveringRect( wpos, wpos + ImVec2( stw * 7, ty ) );
}
void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, const AddrStat& ipcnt, const AddrStat& iptotal, const AddrStat& ipmax, const Worker* worker )
void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t ipcnt, uint32_t iptotal, uint32_t ipmax, const Worker* worker )
{
const auto ty = ImGui::GetFontSize();
auto draw = ImGui::GetWindowDrawList();
@ -2357,9 +2188,9 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, const Add
}
bool mouseHandled = false;
if( iptotal.local + iptotal.ext != 0 )
if( iptotal != 0 )
{
if( ( m_childCalls && ipcnt.local + ipcnt.ext == 0 ) || ( !m_childCalls && ipcnt.local == 0 ) )
if( ipcnt == 0 )
{
const auto ts = ImGui::CalcTextSize( " " );
ImGui::ItemSize( ImVec2( 7 * ts.x, ts.y ) );
@ -2367,29 +2198,12 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, const Add
else
{
auto sit = m_srcSampleSelect.find( lineNum );
bool hover;
if( m_childCalls )
{
hover = PrintPercentage( 100.f * ( ipcnt.local + ipcnt.ext ) / ( iptotal.local + iptotal.ext ), sit == m_srcSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF );
}
else
{
hover = PrintPercentage( 100.f * ipcnt.local / iptotal.local, sit == m_srcSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF );
}
if( hover )
if( PrintPercentage( 100.f * ipcnt / iptotal, sit == m_srcSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF ) )
{
if( m_font ) ImGui::PopFont();
ImGui::BeginTooltip();
if( ipcnt.local )
{
if( worker ) TextFocused( "Local time:", TimeToString( ipcnt.local * worker->GetSamplingPeriod() ) );
TextFocused( "Local samples:", RealToString( ipcnt.local ) );
}
if( ipcnt.ext )
{
if( worker ) TextFocused( "Child time:", TimeToString( ipcnt.ext * worker->GetSamplingPeriod() ) );
TextFocused( "Child samples:", RealToString( ipcnt.ext ) );
}
if( worker ) TextFocused( "Time:", TimeToString( ipcnt * worker->GetSamplingPeriod() ) );
TextFocused( "Sample count:", RealToString( ipcnt ) );
ImGui::EndTooltip();
if( m_font ) ImGui::PushFont( m_font );
@ -2449,14 +2263,7 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, const Add
m_srcGroupSelect = -1;
}
}
if( m_childCalls )
{
draw->AddLine( wpos + ImVec2( 0, 1 ), wpos + ImVec2( 0, ty-2 ), GetHotnessColor( ipcnt.local + ipcnt.ext, ipmax.local + ipmax.ext ) );
}
else
{
draw->AddLine( wpos + ImVec2( 0, 1 ), wpos + ImVec2( 0, ty-2 ), GetHotnessColor( ipcnt.local, ipmax.local ) );
}
draw->AddLine( wpos + ImVec2( 0, 1 ), wpos + ImVec2( 0, ty-2 ), GetHotnessColor( ipcnt, ipmax ) );
}
ImGui::SameLine( 0, ty );
}
@ -2542,7 +2349,7 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, const Add
draw->AddLine( wpos + ImVec2( 0, ty+2 ), wpos + ImVec2( w, ty+2 ), 0x08FFFFFF );
}
void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const AddrStat& iptotal, const AddrStat& ipmax, const Worker& worker, uint64_t& jumpOut, int maxAddrLen, View& view )
void SourceView::RenderAsmLine( AsmLine& line, uint32_t ipcnt, uint32_t iptotal, uint32_t ipmax, const Worker& worker, uint64_t& jumpOut, int maxAddrLen, View& view )
{
const auto ty = ImGui::GetFontSize();
auto draw = ImGui::GetWindowDrawList();
@ -2563,9 +2370,9 @@ void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const Addr
const auto asmIdx = &line - m_asm.data();
if( iptotal.local + iptotal.ext != 0 )
if( iptotal != 0 )
{
if( ( m_childCalls && ipcnt.local + ipcnt.ext == 0 ) || ( !m_childCalls && ipcnt.local == 0 ) )
if( ipcnt == 0 )
{
const auto ts = ImGui::CalcTextSize( " " );
ImGui::ItemSize( ImVec2( 7 * ts.x, ts.y ) );
@ -2574,16 +2381,7 @@ void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const Addr
{
const auto idx = &line - m_asm.data();
auto sit = m_asmSampleSelect.find( idx );
bool hover;
if( m_childCalls )
{
hover = PrintPercentage( 100.f * ( ipcnt.local + ipcnt.ext ) / ( iptotal.local + iptotal.ext ), sit == m_asmSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF );
}
else
{
hover = PrintPercentage( 100.f * ipcnt.local / iptotal.local, sit == m_asmSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF );
}
if( hover )
if( PrintPercentage( 100.f * ipcnt / iptotal, sit == m_asmSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF ) )
{
uint64_t symAddrParents = m_baseAddr;
auto inlineList = worker.GetInlineSymbolList( m_baseAddr, m_codeLen );
@ -2605,27 +2403,17 @@ void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const Addr
inlineList++;
}
}
const auto& stats = *worker.GetSymbolStats( symAddrParents );
assert( !stats.parents.empty() );
if( m_font ) ImGui::PopFont();
ImGui::BeginTooltip();
if( ipcnt.local )
{
TextFocused( "Local time:", TimeToString( ipcnt.local * worker.GetSamplingPeriod() ) );
TextFocused( "Local samples:", RealToString( ipcnt.local ) );
}
if( ipcnt.ext )
{
TextFocused( "Child time:", TimeToString( ipcnt.ext * worker.GetSamplingPeriod() ) );
TextFocused( "Child samples:", RealToString( ipcnt.ext ) );
}
const auto& stats = *worker.GetSymbolStats( symAddrParents );
if( !stats.parents.empty() )
{
ImGui::Separator();
TextFocused( "Entry call stacks:", RealToString( stats.parents.size() ) );
ImGui::SameLine();
TextDisabledUnformatted( "(middle click to view)" );
}
TextFocused( "Time:", TimeToString( ipcnt * worker.GetSamplingPeriod() ) );
TextFocused( "Sample count:", RealToString( ipcnt ) );
ImGui::Separator();
TextFocused( "Entry call stacks:", RealToString( stats.parents.size() ) );
ImGui::SameLine();
TextDisabledUnformatted( "(middle click to view)" );
ImGui::EndTooltip();
if( m_font ) ImGui::PushFont( m_font );
@ -2682,19 +2470,12 @@ void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const Addr
m_asmSampleSelect.clear();
m_asmGroupSelect = -1;
}
else if( !stats.parents.empty() && ImGui::IsMouseClicked( 2 ) )
else if( ImGui::IsMouseClicked( 2 ) )
{
view.ShowSampleParents( symAddrParents );
}
}
if( m_childCalls )
{
draw->AddLine( wpos + ImVec2( 0, 1 ), wpos + ImVec2( 0, ty-2 ), GetHotnessColor( ipcnt.local + ipcnt.ext, ipmax.local + ipmax.ext ) );
}
else
{
draw->AddLine( wpos + ImVec2( 0, 1 ), wpos + ImVec2( 0, ty-2 ), GetHotnessColor( ipcnt.local, ipmax.local ) );
}
draw->AddLine( wpos + ImVec2( 0, 1 ), wpos + ImVec2( 0, ty-2 ), GetHotnessColor( ipcnt, ipmax ) );
}
ImGui::SameLine( 0, ty );
}
@ -2881,7 +2662,7 @@ void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const Addr
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 == 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 );
draw->AddLine( wpos + ImVec2( xoff + JumpSeparation * mjl + th2, th2 ), wpos + ImVec2( xoff + JumpSeparation * mjl + th2 + JumpArrow / 2, th2 ), col );
draw->AddLine( wpos + ImVec2( xoff + JumpSeparation * mjl + th2, th2 ), wpos + ImVec2( xoff + JumpSeparation * mjl + th2 + th4, th2 - th4 ), col );
@ -3364,18 +3145,17 @@ void SourceView::SelectAsmLinesHover( uint32_t file, uint32_t line, const Worker
}
}
void SourceView::GatherIpStats( uint64_t baseAddr, AddrStat& iptotalSrc, AddrStat& iptotalAsm, unordered_flat_map<uint64_t, AddrStat>& ipcountSrc, unordered_flat_map<uint64_t, AddrStat>& ipcountAsm, AddrStat& ipmaxSrc, AddrStat& ipmaxAsm, const Worker& worker, bool limitView, const View& view )
void SourceView::GatherIpStats( uint64_t addr, uint32_t& iptotalSrc, uint32_t& iptotalAsm, unordered_flat_map<uint64_t, uint32_t>& ipcountSrc, unordered_flat_map<uint64_t, uint32_t>& ipcountAsm, uint32_t& ipmaxSrc, uint32_t& ipmaxAsm, const Worker& worker, bool limitView, const View& view )
{
const auto slzReady = worker.AreSourceLocationZonesReady();
auto filename = m_source.filename();
if( limitView )
{
auto vec = worker.GetSamplesForSymbol( baseAddr );
auto vec = worker.GetSamplesForSymbol( addr );
if( !vec ) return;
auto it = std::lower_bound( vec->begin(), vec->end(), view.m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );
if( it == vec->end() ) return;
auto end = std::lower_bound( it, vec->end(), view.m_statRange.max, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );
iptotalAsm.local += end - it;
iptotalAsm += end - it;
while( it != end )
{
if( filename )
@ -3392,16 +3172,16 @@ void SourceView::GatherIpStats( uint64_t baseAddr, AddrStat& iptotalSrc, AddrSta
auto sit = ipcountSrc.find( line );
if( sit == ipcountSrc.end() )
{
ipcountSrc.emplace( line, AddrStat { 1, 0 } );
if( ipmaxSrc.local < 1 ) ipmaxSrc.local = 1;
ipcountSrc.emplace( line, 1 );
if( ipmaxSrc < 1 ) ipmaxSrc = 1;
}
else
{
const auto sum = sit->second.local + 1;
sit->second.local = sum;
if( ipmaxSrc.local < sum ) ipmaxSrc.local = sum;
const auto sum = sit->second + 1;
sit->second = sum;
if( ipmaxSrc < sum ) ipmaxSrc = sum;
}
iptotalSrc.local++;
iptotalSrc++;
}
}
}
@ -3411,14 +3191,14 @@ void SourceView::GatherIpStats( uint64_t baseAddr, AddrStat& iptotalSrc, AddrSta
auto sit = ipcountAsm.find( addr );
if( sit == ipcountAsm.end() )
{
ipcountAsm.emplace( addr, AddrStat{ 1, 0 } );
if( ipmaxAsm.local < 1 ) ipmaxAsm.local = 1;
ipcountAsm.emplace( addr, 1 );
if( ipmaxAsm < 1 ) ipmaxAsm = 1;
}
else
{
const auto sum = sit->second.local + 1;
sit->second.local = sum;
if( ipmaxAsm.local < sum ) ipmaxAsm.local = sum;
const auto sum = sit->second + 1;
sit->second = sum;
if( ipmaxAsm < sum ) ipmaxAsm = sum;
}
++it;
@ -3426,20 +3206,10 @@ void SourceView::GatherIpStats( uint64_t baseAddr, AddrStat& iptotalSrc, AddrSta
}
else
{
auto ipmap = worker.GetSymbolInstructionPointers( baseAddr );
auto ipmap = worker.GetSymbolInstructionPointers( addr );
if( !ipmap ) return;
for( auto& ip : *ipmap )
{
auto addr = worker.GetCanonicalPointer( ip.first );
assert( ipcountAsm.find( addr ) == ipcountAsm.end() );
auto cp = slzReady ? worker.GetChildSamples( addr ) : nullptr;
const uint32_t ccnt = cp ? (uint32_t)cp->size() : 0;
ipcountAsm.emplace( addr, AddrStat { ip.second, ccnt } );
iptotalAsm.local += ip.second;
iptotalAsm.ext += ccnt;
if( ipmaxAsm.local < ip.second ) ipmaxAsm.local = ip.second;
if( ipmaxAsm.ext < ccnt ) ipmaxAsm.ext = ccnt;
if( filename )
{
auto frame = worker.GetCallstackFrame( ip.first );
@ -3454,89 +3224,35 @@ void SourceView::GatherIpStats( uint64_t baseAddr, AddrStat& iptotalSrc, AddrSta
auto it = ipcountSrc.find( line );
if( it == ipcountSrc.end() )
{
ipcountSrc.emplace( line, AddrStat{ ip.second, ccnt } );
if( ipmaxSrc.local < ip.second ) ipmaxSrc.local = ip.second;
if( ipmaxSrc.ext < ccnt ) ipmaxSrc.ext = ccnt;
ipcountSrc.emplace( line, ip.second );
if( ipmaxSrc < ip.second ) ipmaxSrc = ip.second;
}
else
{
const auto sum = it->second.local + ip.second;
const auto csum = it->second.ext + ccnt;
it->second.local = sum;
it->second.ext = csum;
if( ipmaxSrc.local < sum ) ipmaxSrc.local = sum;
if( ipmaxSrc.ext < csum ) ipmaxSrc.ext = csum;
const auto sum = it->second + ip.second;
it->second = sum;
if( ipmaxSrc < sum ) ipmaxSrc = sum;
}
iptotalSrc.local += ip.second;
iptotalSrc.ext += ccnt;
iptotalSrc += ip.second;
}
}
}
}
auto addr = worker.GetCanonicalPointer( ip.first );
assert( ipcountAsm.find( addr ) == ipcountAsm.end() );
ipcountAsm.emplace( addr, ip.second );
iptotalAsm += ip.second;
if( ipmaxAsm < ip.second ) ipmaxAsm = ip.second;
}
}
}
void SourceView::GatherAdditionalIpStats( uint64_t baseAddr, AddrStat& iptotalSrc, AddrStat& iptotalAsm, unordered_flat_map<uint64_t, AddrStat>& ipcountSrc, unordered_flat_map<uint64_t, AddrStat>& ipcountAsm, AddrStat& ipmaxSrc, AddrStat& ipmaxAsm, const Worker& worker, bool limitView, const View& view )
{
if( !worker.AreSourceLocationZonesReady() ) return;
auto filename = m_source.filename();
if( limitView )
{
}
else
{
auto sym = worker.GetSymbolData( baseAddr );
if( sym )
{
for( uint64_t ip = baseAddr; ip < baseAddr + sym->size.Val(); ip++ )
{
if( ipcountAsm.find( ip ) != ipcountAsm.end() ) continue;
auto cp = worker.GetChildSamples( ip );
if( !cp ) continue;
const auto ccnt = (uint32_t)cp->size();
ipcountAsm.emplace( ip, AddrStat { 0, ccnt } );
iptotalAsm.ext += ccnt;
if( ipmaxAsm.ext < ccnt ) ipmaxAsm.ext = ccnt;
if( filename )
{
auto frame = worker.GetCallstackFrame( worker.PackPointer( ip ) );
if( frame )
{
auto ffn = worker.GetString( frame->data[0].file );
if( strcmp( ffn, filename ) == 0 )
{
const auto line = frame->data[0].line;
if( line != 0 )
{
auto it = ipcountSrc.find( line );
if( it == ipcountSrc.end() )
{
ipcountSrc.emplace( line, AddrStat{ 0, ccnt } );
if( ipmaxSrc.ext < ccnt ) ipmaxSrc.ext = ccnt;
}
else
{
const auto csum = it->second.ext + ccnt;
it->second.ext = csum;
if( ipmaxSrc.ext < csum ) ipmaxSrc.ext = csum;
}
iptotalSrc.ext += ccnt;
}
}
}
}
}
}
}
}
uint32_t SourceView::CountAsmIpStats( uint64_t baseAddr, const Worker& worker, bool limitView, const View& view )
uint32_t SourceView::CountAsmIpStats( uint64_t addr, const Worker& worker, bool limitView, const View& view )
{
if( limitView )
{
auto vec = worker.GetSamplesForSymbol( baseAddr );
auto vec = worker.GetSamplesForSymbol( addr );
if( !vec ) return 0;
auto it = std::lower_bound( vec->begin(), vec->end(), view.m_statRange.min, [] ( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs; } );
if( it == vec->end() ) return 0;
@ -3546,7 +3262,7 @@ uint32_t SourceView::CountAsmIpStats( uint64_t baseAddr, const Worker& worker, b
else
{
uint32_t cnt = 0;
auto ipmap = worker.GetSymbolInstructionPointers( baseAddr );
auto ipmap = worker.GetSymbolInstructionPointers( addr );
if( !ipmap ) return 0;
for( auto& ip : *ipmap ) cnt += ip.second;
return cnt;

View File

@ -100,19 +100,6 @@ private:
DisplayMixed
};
struct AddrStat
{
uint32_t local;
uint32_t ext;
AddrStat& operator+=( const AddrStat& other )
{
local += other.local;
ext += other.ext;
return *this;
}
};
public:
using GetWindowCallback = void*(*)();
@ -136,19 +123,18 @@ private:
void RenderSimpleSourceView();
void RenderSymbolView( const Worker& worker, View& view );
void RenderSymbolSourceView( const AddrStat& iptotal, const unordered_flat_map<uint64_t, AddrStat>& ipcount, const unordered_flat_map<uint64_t, AddrStat>& ipcountAsm, const AddrStat& ipmax, const Worker& worker, const View& view );
uint64_t RenderSymbolAsmView( const AddrStat& iptotal, const unordered_flat_map<uint64_t, AddrStat>& ipcount, const AddrStat& ipmax, const Worker& worker, View& view );
void RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<uint64_t, uint32_t> ipcount, unordered_flat_map<uint64_t, uint32_t> ipcountAsm, uint32_t ipmax, const Worker& worker, const View& view );
uint64_t RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<uint64_t, uint32_t> ipcount, uint32_t ipmax, const Worker& worker, View& view );
void RenderLine( const Tokenizer::Line& line, int lineNum, const AddrStat& ipcnt, const AddrStat& iptotal, const AddrStat& ipmax, const Worker* worker );
void RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const AddrStat& iptotal, const AddrStat& ipmax, const Worker& worker, uint64_t& jumpOut, int maxAddrLen, View& view );
void RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t ipcnt, uint32_t iptotal, uint32_t ipmax, const Worker* worker );
void RenderAsmLine( AsmLine& line, uint32_t ipcnt, uint32_t iptotal, uint32_t ipmax, const Worker& worker, uint64_t& jumpOut, int maxAddrLen, View& view );
void SelectLine( uint32_t line, const Worker* worker, bool changeAsmLine = true, uint64_t targetAddr = 0 );
void SelectAsmLines( uint32_t file, uint32_t line, const Worker& worker, bool changeAsmLine = true, uint64_t targetAddr = 0 );
void SelectAsmLinesHover( uint32_t file, uint32_t line, const Worker& worker );
void GatherIpStats( uint64_t baseAddr, AddrStat& iptotalSrc, AddrStat& iptotalAsm, unordered_flat_map<uint64_t, AddrStat>& ipcountSrc, unordered_flat_map<uint64_t, AddrStat>& ipcountAsm, AddrStat& ipmaxSrc, AddrStat& ipmaxAsm, const Worker& worker, bool limitView, const View& view );
void GatherAdditionalIpStats( uint64_t baseAddr, AddrStat& iptotalSrc, AddrStat& iptotalAsm, unordered_flat_map<uint64_t, AddrStat>& ipcountSrc, unordered_flat_map<uint64_t, AddrStat>& ipcountAsm, AddrStat& ipmaxSrc, AddrStat& ipmaxAsm, const Worker& worker, bool limitView, const View& view );
uint32_t CountAsmIpStats( uint64_t baseAddr, const Worker& worker, bool limitView, const View& view );
void GatherIpStats( uint64_t addr, uint32_t& iptotalSrc, uint32_t& iptotalAsm, unordered_flat_map<uint64_t, uint32_t>& ipcountSrc, unordered_flat_map<uint64_t, uint32_t>& ipcountAsm, uint32_t& ipmaxSrc, uint32_t& ipmaxAsm, const Worker& worker, bool limitView, const View& view );
uint32_t CountAsmIpStats( uint64_t addr, const Worker& worker, bool limitView, const View& view );
void SelectMicroArchitecture( const char* moniker );
@ -183,7 +169,6 @@ private:
uint8_t m_maxAsmBytes;
bool m_atnt;
uint64_t m_jumpPopupAddr;
bool m_childCalls;
SourceContents m_source;
SourceContents m_sourceTooltip;

View File

@ -618,7 +618,7 @@ bool View::DrawImpl()
bool keepOpen = true;
char tmp[2048];
sprintf( tmp, "%s###Connection", m_worker.GetAddr().c_str() );
ImGui::Begin( tmp, &keepOpen, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse );
ImGui::Begin( tmp, &keepOpen, ImGuiWindowFlags_AlwaysAutoResize );
TextCentered( ICON_FA_WIFI );
ImGui::TextUnformatted( "Waiting for connection..." );
DrawWaitingDots( s_time );
@ -13801,15 +13801,6 @@ void View::DrawInfo()
}
TextFocused( "Call stack samples:", RealToString( m_worker.GetCallstackSampleCount() ) );
TextFocused( "Ghost zones:", RealToString( m_worker.GetGhostZonesCount() ) );
#ifndef TRACY_NO_STATISTICS
TextFocused( "Child sample symbols:", RealToString( m_worker.GetChildSamplesCountSyms() ) );
if( ImGui::IsItemHovered() )
{
ImGui::BeginTooltip();
TextFocused( "Child samples:", RealToString( m_worker.GetChildSamplesCountFull() ) );
ImGui::EndTooltip();
}
#endif
TextFocused( "Frame images:", RealToString( ficnt ) );
if( ficnt != 0 && ImGui::IsItemHovered() )
{

View File

@ -1830,29 +1830,12 @@ Worker::Worker( FileRead& f, EventType::Type eventMask, bool bgTasks )
it->second.push_back_non_empty( SampleDataRange { time, ip } );
}
}
for( uint16_t i=1; i<callstack.size(); i++ )
{
auto addr = GetCanonicalPointer( callstack[i] );
auto it = m_data.childSamples.find( addr );
if( it == m_data.childSamples.end() )
{
m_data.childSamples.emplace( addr, Vector<Int48>( time ) );
}
else
{
it->second.push_back_non_empty( time );
}
}
}
}
for( auto& v : m_data.symbolSamples )
{
pdqsort_branchless( v.second.begin(), v.second.end(), []( const auto& lhs, const auto& rhs ) { return lhs.time.Val() < rhs.time.Val(); } );
}
for( auto& v : m_data.childSamples )
{
pdqsort_branchless( v.second.begin(), v.second.end(), []( const auto& lhs, const auto& rhs ) { return lhs.Val() < rhs.Val(); } );
}
std::lock_guard<std::mutex> lock( m_data.lock );
m_data.symbolSamplesReady = true;
} ) );
@ -2000,18 +1983,6 @@ uint64_t Worker::GetContextSwitchPerCpuCount() const
return cnt;
}
#ifndef TRACY_NO_STATISTICS
uint64_t Worker::GetChildSamplesCountFull() const
{
uint64_t cnt = 0;
for( auto& v : m_data.childSamples )
{
cnt += v.second.size();
}
return cnt;
}
#endif
uint64_t Worker::GetPidFromTid( uint64_t tid ) const
{
auto it = m_data.tidToPid.find( tid );
@ -2225,14 +2196,6 @@ const Vector<SampleDataRange>* Worker::GetSamplesForSymbol( uint64_t symAddr ) c
if( it == m_data.symbolSamples.end() ) return nullptr;
return &it->second;
}
const Vector<Int48>* Worker::GetChildSamples( uint64_t addr ) const
{
assert( m_data.symbolSamplesReady );
auto it = m_data.childSamples.find( addr );
if( it == m_data.childSamples.end() ) return nullptr;
return &it->second;
}
#endif
const SymbolData* Worker::GetSymbolData( uint64_t sym ) const
@ -5602,11 +5565,11 @@ MemEvent* Worker::ProcessMemFreeImpl( uint64_t memname, MemData& memdata, const
const auto refTime = m_refTimeSerial + ev.time;
m_refTimeSerial = refTime;
if( ev.ptr == 0 ) return nullptr;
auto it = memdata.active.find( ev.ptr );
if( it == memdata.active.end() )
{
if( ev.ptr == 0 ) return nullptr;
if( !m_ignoreMemFreeFaults )
{
CheckThreadString( ev.thread );
@ -5830,19 +5793,6 @@ void Worker::ProcessCallstackSample( const QueueCallstackSample& ev )
}
}
}
for( uint16_t i=1; i<cs.size(); i++ )
{
auto addr = GetCanonicalPointer( cs[i] );
auto it = m_data.childSamples.find( addr );
if( it == m_data.childSamples.end() )
{
m_data.childSamples.emplace( addr, Vector<Int48>( sd.time ) );
}
else
{
it->second.push_back_non_empty( sd.time );
}
}
const auto framesKnown = UpdateSampleStatistics( m_pendingCallstackId, 1, true );
assert( td->samples.size() > td->ghostIdx );

View File

@ -294,7 +294,6 @@ private:
unordered_flat_map<uint64_t, unordered_flat_map<CallstackFrameId, uint32_t, CallstackFrameIdHash, CallstackFrameIdCompare>> instructionPointersMap;
unordered_flat_map<uint64_t, Vector<SampleDataRange>> symbolSamples;
unordered_flat_map<CallstackFrameId, Vector<SampleDataRange>, CallstackFrameIdHash, CallstackFrameIdCompare> pendingSymbolSamples;
unordered_flat_map<uint64_t, Vector<Int48>> childSamples;
bool newFramesWereReceived = false;
bool callstackSamplesReady = false;
bool ghostZonesReady = false;
@ -445,10 +444,6 @@ public:
uint64_t GetGhostZonesCount() const { return m_data.ghostCnt; }
uint32_t GetFrameImageCount() const { return (uint32_t)m_data.frameImage.size(); }
uint64_t GetStringsCount() const { return m_data.strings.size() + m_data.stringData.size(); }
#ifndef TRACY_NO_STATISTICS
uint64_t GetChildSamplesCountSyms() const { return m_data.childSamples.size(); }
uint64_t GetChildSamplesCountFull() const;
#endif
uint64_t GetFrameOffset() const { return m_data.frameOffset; }
const FrameData* GetFramesBase() const { return m_data.framesBase; }
const Vector<FrameData*>& GetFrames() const { return m_data.frames.Data(); }
@ -502,7 +497,6 @@ public:
const VarArray<CallstackFrameId>& GetParentCallstack( uint32_t idx ) const { return *m_data.parentCallstackPayload[idx]; }
const CallstackFrameData* GetParentCallstackFrame( const CallstackFrameId& ptr ) const;
const Vector<SampleDataRange>* GetSamplesForSymbol( uint64_t symAddr ) const;
const Vector<Int48>* GetChildSamples( uint64_t addr ) const;
#endif
const CrashEvent& GetCrashEvent() const { return m_data.crashEvent; }