mirror of
https://github.com/wolfpld/tracy
synced 2025-01-15 20:08:00 +00:00
Compare commits
37 Commits
d71d76414b
...
4a1142fddf
Author | SHA1 | Date | |
---|---|---|---|
|
4a1142fddf | ||
|
be963f184c | ||
|
da9a32fd09 | ||
|
0bbda5ea11 | ||
|
e189f596ac | ||
|
cbf8550a45 | ||
|
d234f4dbe4 | ||
|
fb872fa088 | ||
|
cba72859e9 | ||
|
141a4bc0fe | ||
|
c7da9b1092 | ||
|
66ef71cf7b | ||
|
ef93c69ee9 | ||
|
2009f63e32 | ||
|
a5afa2cb4e | ||
|
4970c48c51 | ||
|
c859d655ad | ||
|
50a1faa880 | ||
|
5f97c484f1 | ||
|
046881e32f | ||
|
22a8c53e8b | ||
|
b217e00dd9 | ||
|
526d0cd22a | ||
|
c5eb398319 | ||
|
8db9bcf7f8 | ||
|
0d8ee47231 | ||
|
3845c392fa | ||
|
55efa64b3f | ||
|
32e3c0ebb1 | ||
|
34b80ac52f | ||
|
2f6adf3641 | ||
|
ffe8aebfbd | ||
|
df462f109d | ||
|
4dc6222ba1 | ||
|
fa8c99fd74 | ||
|
0476e851ff | ||
|
aee39d3fcd |
1
NEWS
1
NEWS
@ -12,6 +12,7 @@ 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)
|
||||
|
@ -512,7 +512,7 @@ LZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const si
|
||||
/*-************************************
|
||||
* Common functions
|
||||
**************************************/
|
||||
static unsigned LZ4_NbCommonBytes (reg_t val)
|
||||
LZ4_FORCE_INLINE unsigned LZ4_NbCommonBytes (reg_t val)
|
||||
{
|
||||
assert(val != 0);
|
||||
if (LZ4_isLittleEndian()) {
|
||||
|
@ -3244,6 +3244,8 @@ 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.
|
||||
|
@ -124,7 +124,7 @@ std::vector<Tokenizer::Token> Tokenizer::Tokenize( const char* begin, const char
|
||||
}
|
||||
else
|
||||
{
|
||||
while( begin != end && isspace( *begin ) ) begin++;
|
||||
while( begin != end && isspace( (uint8_t)*begin ) ) begin++;
|
||||
if( first && begin < end && *begin == '#' )
|
||||
{
|
||||
if( *(end-1) == '\\' ) m_isInPreprocessor = true;
|
||||
|
@ -88,6 +88,7 @@ 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 )
|
||||
@ -863,6 +864,7 @@ 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;
|
||||
@ -873,7 +875,7 @@ void SourceView::RenderSimpleSourceView()
|
||||
m_targetLine = 0;
|
||||
ImGui::SetScrollHereY();
|
||||
}
|
||||
RenderLine( line, lineNum++, 0, 0, 0, nullptr );
|
||||
RenderLine( line, lineNum++, zero, zero, zero, nullptr );
|
||||
}
|
||||
const auto win = ImGui::GetCurrentWindowRead();
|
||||
m_srcWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;
|
||||
@ -886,7 +888,7 @@ void SourceView::RenderSimpleSourceView()
|
||||
{
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
{
|
||||
RenderLine( lines[i], i+1, 0, 0, 0, nullptr );
|
||||
RenderLine( lines[i], i+1, zero, zero, zero, nullptr );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1092,12 +1094,13 @@ void SourceView::RenderSymbolView( const Worker& worker, View& view )
|
||||
TextFocused( ICON_FA_WEIGHT_HANGING " Code size:", MemSizeToString( m_codeLen ) );
|
||||
}
|
||||
|
||||
uint32_t iptotalSrc = 0, iptotalAsm = 0;
|
||||
uint32_t ipmaxSrc = 0, ipmaxAsm = 0;
|
||||
unordered_flat_map<uint64_t, uint32_t> ipcountSrc, ipcountAsm;
|
||||
AddrStat iptotalSrc = {}, iptotalAsm = {};
|
||||
AddrStat ipmaxSrc = {}, ipmaxAsm = {};
|
||||
unordered_flat_map<uint64_t, AddrStat> 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
|
||||
{
|
||||
@ -1112,18 +1115,78 @@ void SourceView::RenderSymbolView( const Worker& worker, View& view )
|
||||
iptr++;
|
||||
}
|
||||
}
|
||||
GatherAdditionalIpStats( m_symAddr, iptotalSrc, iptotalAsm, ipcountSrc, ipcountAsm, ipmaxSrc, ipmaxAsm, worker, limitView, view );
|
||||
iptotalSrc = iptotalAsm;
|
||||
}
|
||||
if( iptotalAsm > 0 )
|
||||
const auto slzReady = worker.AreSourceLocationZonesReady();
|
||||
if( ( iptotalAsm.local + iptotalAsm.ext ) > 0 || ( view.m_statRange.active && worker.GetSamplesForSymbol( m_baseAddr ) ) )
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( ICON_FA_STOPWATCH " Time:", TimeToString( iptotalAsm * worker.GetSamplingPeriod() ) );
|
||||
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();
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( ICON_FA_EYE_DROPPER " Samples:", RealToString( iptotalAsm ) );
|
||||
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 ) );
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
@ -1139,7 +1202,7 @@ void SourceView::RenderSymbolView( const Worker& worker, View& view )
|
||||
if( ImGui::IsItemHovered() )
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextUnformatted( "Waiting for background tasks to finish" );
|
||||
ImGui::TextUnformatted( "Please wait, processing data..." );
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@ -1188,6 +1251,8 @@ 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 );
|
||||
@ -1230,10 +1295,9 @@ static uint32_t GetHotnessColor( uint32_t ipSum, uint32_t maxIpCount )
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 )
|
||||
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 )
|
||||
{
|
||||
if( m_sourceFiles.empty() )
|
||||
{
|
||||
@ -1315,15 +1379,15 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t totalSamples = 0;
|
||||
unordered_flat_map<uint32_t, uint32_t> fileCounts;
|
||||
AddrStat totalSamples = {};
|
||||
unordered_flat_map<uint32_t, AddrStat> fileCounts;
|
||||
for( auto& v : m_asm )
|
||||
{
|
||||
uint32_t srcline;
|
||||
const auto srcidx = worker.GetLocationForAddress( v.addr, srcline );
|
||||
if( srcline != 0 )
|
||||
{
|
||||
uint32_t cnt = 0;
|
||||
AddrStat cnt = {};
|
||||
auto ait = ipcountAsm.find( v.addr );
|
||||
if( ait != ipcountAsm.end() ) cnt = ait->second;
|
||||
|
||||
@ -1332,19 +1396,27 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
{
|
||||
fileCounts.emplace( srcidx.Idx(), cnt );
|
||||
}
|
||||
else if( cnt != 0 )
|
||||
else
|
||||
{
|
||||
fit->second += cnt;
|
||||
}
|
||||
totalSamples += cnt;
|
||||
}
|
||||
}
|
||||
std::vector<std::pair<uint32_t, uint32_t>> fileCountsVec;
|
||||
std::vector<std::pair<uint32_t, AddrStat>> fileCountsVec;
|
||||
fileCountsVec.reserve( fileCounts.size() );
|
||||
for( auto& v : fileCounts ) fileCountsVec.emplace_back( v.first, v.second );
|
||||
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; } );
|
||||
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; } );
|
||||
}
|
||||
|
||||
if( totalSamples != 0 )
|
||||
const auto hasSamples = totalSamples.local + totalSamples.ext != 0;
|
||||
if( hasSamples )
|
||||
{
|
||||
ImGui::Columns( 2 );
|
||||
static bool widthSet = false;
|
||||
@ -1359,21 +1431,48 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
}
|
||||
for( auto& v : fileCountsVec )
|
||||
{
|
||||
if( totalSamples != 0 )
|
||||
if( hasSamples )
|
||||
{
|
||||
auto fit = fileCounts.find( v.first );
|
||||
assert( fit != fileCounts.end() );
|
||||
if( fit->second != 0 )
|
||||
if( fit->second.local + fit->second.ext != 0 )
|
||||
{
|
||||
ImGui::TextUnformatted( TimeToString( fit->second * worker.GetSamplingPeriod() ) );
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled( "(%.2f%%)", 100.f * fit->second / totalSamples );
|
||||
if( m_childCalls )
|
||||
{
|
||||
ImGui::TextUnformatted( TimeToString( ( fit->second.local + fit->second.ext ) * worker.GetSamplingPeriod() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::TextUnformatted( TimeToString( fit->second.local * worker.GetSamplingPeriod() ) );
|
||||
}
|
||||
if( ImGui::IsItemHovered() )
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
TextFocused( "Sample count:", RealToString( fit->second ) );
|
||||
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 ) );
|
||||
}
|
||||
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();
|
||||
}
|
||||
@ -1405,9 +1504,9 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
{
|
||||
TextDisabledUnformatted( fstr );
|
||||
}
|
||||
if( totalSamples != 0 ) ImGui::NextColumn();
|
||||
if( hasSamples ) ImGui::NextColumn();
|
||||
}
|
||||
if( totalSamples != 0 ) ImGui::EndColumns();
|
||||
if( hasSamples ) ImGui::EndColumns();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
@ -1429,7 +1528,7 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
const auto tmp = RealToString( lineCount );
|
||||
const auto maxLine = strlen( tmp );
|
||||
auto lx = ts * maxLine + ty + round( ts*0.4f );
|
||||
if( iptotal != 0 ) lx += ts * 7 + ty;
|
||||
if( iptotal.local + iptotal.ext != 0 ) lx += ts * 7 + ty;
|
||||
if( !m_asm.empty() )
|
||||
{
|
||||
const auto tmp = RealToString( m_asm.size() );
|
||||
@ -1438,6 +1537,7 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
}
|
||||
draw->AddLine( wpos + ImVec2( lx, 0 ), wpos + ImVec2( lx, wh ), 0x08FFFFFF );
|
||||
|
||||
const AddrStat zero = {};
|
||||
m_selectedAddressesHover.clear();
|
||||
if( m_targetLine != 0 )
|
||||
{
|
||||
@ -1449,7 +1549,7 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
m_targetLine = 0;
|
||||
ImGui::SetScrollHereY();
|
||||
}
|
||||
RenderLine( line, lineNum++, 0, iptotal, ipmax, &worker );
|
||||
RenderLine( line, lineNum++, zero, iptotal, ipmax, &worker );
|
||||
}
|
||||
const auto win = ImGui::GetCurrentWindowRead();
|
||||
m_srcWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;
|
||||
@ -1460,11 +1560,11 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
clipper.Begin( (int)lines.size() );
|
||||
while( clipper.Step() )
|
||||
{
|
||||
if( iptotal == 0 )
|
||||
if( iptotal.local + iptotal.ext == 0 )
|
||||
{
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
{
|
||||
RenderLine( lines[i], i+1, 0, 0, 0, &worker );
|
||||
RenderLine( lines[i], i+1, zero, zero, zero, &worker );
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1472,7 +1572,7 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
{
|
||||
auto it = ipcount.find( i+1 );
|
||||
const auto ipcnt = it == ipcount.end() ? 0 : it->second;
|
||||
const auto ipcnt = it == ipcount.end() ? zero : it->second;
|
||||
RenderLine( lines[i], i+1, ipcnt, iptotal, ipmax, &worker );
|
||||
}
|
||||
}
|
||||
@ -1496,7 +1596,7 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
draw->AddLine( ImVec2( rect.Min.x, ly ), ImVec2( rect.Max.x, ly ), 0x88888888, 3 );
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint64_t, uint32_t>> ipData;
|
||||
std::vector<std::pair<uint64_t, AddrStat>> 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++ )
|
||||
@ -1510,7 +1610,7 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
{
|
||||
if( addr >= m_baseAddr && addr < m_baseAddr + m_codeLen )
|
||||
{
|
||||
ipData.emplace_back( lineNum, 0 );
|
||||
ipData.emplace_back( lineNum, AddrStat {} );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1527,15 +1627,23 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
while( it != ipData.end() )
|
||||
{
|
||||
const auto firstLine = it->first;
|
||||
uint32_t ipSum = 0;
|
||||
AddrStat ipSum = {};
|
||||
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() );
|
||||
const uint32_t color = ipSum == 0 ? 0x22FFFFFF : GetHotnessColor( ipSum, ipmax );
|
||||
draw->AddRectFilled( ImVec2( x14, ly ), ImVec2( x34, ly+3 ), color );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopClipRect();
|
||||
@ -1546,7 +1654,7 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
|
||||
if( !m_srcSampleSelect.empty() )
|
||||
{
|
||||
uint32_t count = 0;
|
||||
AddrStat count = {};
|
||||
uint32_t numLines = 0;
|
||||
for( auto& idx : m_srcSampleSelect )
|
||||
{
|
||||
@ -1566,17 +1674,43 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_map<ui
|
||||
}
|
||||
ImGui::SameLine();
|
||||
char buf[16];
|
||||
auto end = PrintFloat( buf, buf+16, 100.f * count / iptotal, 2 );
|
||||
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 );
|
||||
}
|
||||
memcpy( end, "%", 2 );
|
||||
TextFocused( "Selected:", buf );
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Time:", TimeToString( count * worker.GetSamplingPeriod() ) );
|
||||
if( m_childCalls )
|
||||
{
|
||||
TextFocused( "Time:", TimeToString( ( count.local + count.ext ) * worker.GetSamplingPeriod() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
TextFocused( "Time:", TimeToString( count.local * worker.GetSamplingPeriod() ) );
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Sample count:", RealToString( count ) );
|
||||
if( m_childCalls )
|
||||
{
|
||||
TextFocused( "Sample count:", RealToString( count.local + count.ext ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
TextFocused( "Sample count:", RealToString( count.local ) );
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
@ -1632,7 +1766,7 @@ static int PrintHexBytes( char* buf, const uint8_t* bytes, size_t len, CpuArchit
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<uint64_t, uint32_t> ipcount, uint32_t ipmax, const Worker& worker, View& view )
|
||||
uint64_t SourceView::RenderSymbolAsmView( const AddrStat& iptotal, const unordered_flat_map<uint64_t, AddrStat>& ipcount, const AddrStat& ipmax, const Worker& worker, View& view )
|
||||
{
|
||||
if( m_disasmFail >= 0 )
|
||||
{
|
||||
@ -1775,6 +1909,7 @@ uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<u
|
||||
uint64_t selJumpTarget;
|
||||
uint64_t jumpOut = 0;
|
||||
|
||||
const AddrStat zero = {};
|
||||
if( m_targetAddr != 0 )
|
||||
{
|
||||
for( auto& line : m_asm )
|
||||
@ -1784,7 +1919,7 @@ uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<u
|
||||
m_targetAddr = 0;
|
||||
ImGui::SetScrollHereY();
|
||||
}
|
||||
RenderAsmLine( line, 0, iptotal, ipmax, worker, jumpOut, maxAddrLen, view );
|
||||
RenderAsmLine( line, zero, iptotal, ipmax, worker, jumpOut, maxAddrLen, view );
|
||||
}
|
||||
const auto win = ImGui::GetCurrentWindowRead();
|
||||
m_asmWidth = win->DC.CursorMaxPos.x - win->DC.CursorStartPos.x;
|
||||
@ -1800,11 +1935,11 @@ uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<u
|
||||
const auto wpos = ImGui::GetCursorScreenPos();
|
||||
static std::vector<uint64_t> insList;
|
||||
insList.clear();
|
||||
if( iptotal == 0 )
|
||||
if( iptotal.local + iptotal.ext == 0 )
|
||||
{
|
||||
for( auto i=clipper.DisplayStart; i<clipper.DisplayEnd; i++ )
|
||||
{
|
||||
RenderAsmLine( m_asm[i], 0, 0, 0, worker, jumpOut, maxAddrLen, view );
|
||||
RenderAsmLine( m_asm[i], zero, zero, zero, worker, jumpOut, maxAddrLen, view );
|
||||
insList.emplace_back( m_asm[i].addr );
|
||||
}
|
||||
}
|
||||
@ -1814,7 +1949,7 @@ uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<u
|
||||
{
|
||||
auto& line = m_asm[i];
|
||||
auto it = ipcount.find( line.addr );
|
||||
const auto ipcnt = it == ipcount.end() ? 0 : it->second;
|
||||
const auto ipcnt = it == ipcount.end() ? zero : it->second;
|
||||
RenderAsmLine( line, ipcnt, iptotal, ipmax, worker, jumpOut, maxAddrLen, view );
|
||||
insList.emplace_back( line.addr );
|
||||
}
|
||||
@ -1825,7 +1960,7 @@ uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<u
|
||||
const auto ts = ImGui::CalcTextSize( " " );
|
||||
const auto th2 = floor( ts.y / 2 );
|
||||
const auto th4 = floor( ts.y / 4 );
|
||||
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 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 minAddr = m_asm[clipper.DisplayStart].addr;
|
||||
const auto maxAddr = m_asm[clipper.DisplayEnd-1].addr;
|
||||
const auto mjl = m_maxJumpLevel;
|
||||
@ -2008,7 +2143,7 @@ uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<u
|
||||
}
|
||||
|
||||
uint32_t selJumpLineStart, selJumpLineEnd, selJumpLineTarget;
|
||||
std::vector<std::pair<uint64_t, uint32_t>> ipData;
|
||||
std::vector<std::pair<uint64_t, AddrStat>> ipData;
|
||||
ipData.reserve( ipcount.size() );
|
||||
if( selJumpStart == 0 )
|
||||
{
|
||||
@ -2042,15 +2177,23 @@ uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<u
|
||||
while( it != ipData.end() )
|
||||
{
|
||||
const auto firstLine = it->first;
|
||||
uint32_t ipSum = 0;
|
||||
AddrStat ipSum = {};
|
||||
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() );
|
||||
const uint32_t color = GetHotnessColor( ipSum, ipmax );
|
||||
draw->AddRectFilled( ImVec2( x40, ly ), ImVec2( x60, ly+3 ), color );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
if( selJumpStart != 0 )
|
||||
@ -2106,7 +2249,7 @@ uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<u
|
||||
|
||||
if( !m_asmSampleSelect.empty() )
|
||||
{
|
||||
uint32_t count = 0;
|
||||
AddrStat count = {};
|
||||
uint32_t numLines = 0;
|
||||
for( auto& idx : m_asmSampleSelect )
|
||||
{
|
||||
@ -2126,17 +2269,43 @@ uint64_t SourceView::RenderSymbolAsmView( uint32_t iptotal, unordered_flat_map<u
|
||||
}
|
||||
ImGui::SameLine();
|
||||
char buf[16];
|
||||
auto end = PrintFloat( buf, buf+16, 100.f * count / iptotal, 2 );
|
||||
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 );
|
||||
}
|
||||
memcpy( end, "%", 2 );
|
||||
TextFocused( "Selected:", buf );
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Time:", TimeToString( count * worker.GetSamplingPeriod() ) );
|
||||
if( m_childCalls )
|
||||
{
|
||||
TextFocused( "Time:", TimeToString( ( count.local + count.ext ) * worker.GetSamplingPeriod() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
TextFocused( "Time:", TimeToString( count.local * worker.GetSamplingPeriod() ) );
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
TextFocused( "Sample count:", RealToString( count ) );
|
||||
if( m_childCalls )
|
||||
{
|
||||
TextFocused( "Sample count:", RealToString( count.local + count.ext ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
TextFocused( "Sample count:", RealToString( count.local ) );
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Spacing();
|
||||
ImGui::SameLine();
|
||||
@ -2172,7 +2341,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, uint32_t ipcnt, uint32_t iptotal, uint32_t ipmax, const Worker* worker )
|
||||
void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, const AddrStat& ipcnt, const AddrStat& iptotal, const AddrStat& ipmax, const Worker* worker )
|
||||
{
|
||||
const auto ty = ImGui::GetFontSize();
|
||||
auto draw = ImGui::GetWindowDrawList();
|
||||
@ -2188,9 +2357,9 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t
|
||||
}
|
||||
|
||||
bool mouseHandled = false;
|
||||
if( iptotal != 0 )
|
||||
if( iptotal.local + iptotal.ext != 0 )
|
||||
{
|
||||
if( ipcnt == 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 ) );
|
||||
@ -2198,12 +2367,29 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t
|
||||
else
|
||||
{
|
||||
auto sit = m_srcSampleSelect.find( lineNum );
|
||||
if( PrintPercentage( 100.f * ipcnt / iptotal, sit == m_srcSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF ) )
|
||||
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( m_font ) ImGui::PopFont();
|
||||
ImGui::BeginTooltip();
|
||||
if( worker ) TextFocused( "Time:", TimeToString( ipcnt * worker->GetSamplingPeriod() ) );
|
||||
TextFocused( "Sample count:", RealToString( ipcnt ) );
|
||||
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 ) );
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
if( m_font ) ImGui::PushFont( m_font );
|
||||
|
||||
@ -2263,7 +2449,14 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t
|
||||
m_srcGroupSelect = -1;
|
||||
}
|
||||
}
|
||||
draw->AddLine( wpos + ImVec2( 0, 1 ), wpos + ImVec2( 0, ty-2 ), GetHotnessColor( ipcnt, ipmax ) );
|
||||
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 ) );
|
||||
}
|
||||
}
|
||||
ImGui::SameLine( 0, ty );
|
||||
}
|
||||
@ -2349,7 +2542,7 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t
|
||||
draw->AddLine( wpos + ImVec2( 0, ty+2 ), wpos + ImVec2( w, ty+2 ), 0x08FFFFFF );
|
||||
}
|
||||
|
||||
void SourceView::RenderAsmLine( AsmLine& line, uint32_t ipcnt, uint32_t iptotal, uint32_t ipmax, const Worker& worker, uint64_t& jumpOut, int maxAddrLen, View& view )
|
||||
void SourceView::RenderAsmLine( AsmLine& line, const AddrStat& ipcnt, const AddrStat& iptotal, const AddrStat& ipmax, const Worker& worker, uint64_t& jumpOut, int maxAddrLen, View& view )
|
||||
{
|
||||
const auto ty = ImGui::GetFontSize();
|
||||
auto draw = ImGui::GetWindowDrawList();
|
||||
@ -2370,9 +2563,9 @@ void SourceView::RenderAsmLine( AsmLine& line, uint32_t ipcnt, uint32_t iptotal,
|
||||
|
||||
const auto asmIdx = &line - m_asm.data();
|
||||
|
||||
if( iptotal != 0 )
|
||||
if( iptotal.local + iptotal.ext != 0 )
|
||||
{
|
||||
if( ipcnt == 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 ) );
|
||||
@ -2381,7 +2574,16 @@ void SourceView::RenderAsmLine( AsmLine& line, uint32_t ipcnt, uint32_t iptotal,
|
||||
{
|
||||
const auto idx = &line - m_asm.data();
|
||||
auto sit = m_asmSampleSelect.find( idx );
|
||||
if( PrintPercentage( 100.f * ipcnt / iptotal, sit == m_asmSampleSelect.end() ? 0xFFFFFFFF : 0xFF8888FF ) )
|
||||
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 )
|
||||
{
|
||||
uint64_t symAddrParents = m_baseAddr;
|
||||
auto inlineList = worker.GetInlineSymbolList( m_baseAddr, m_codeLen );
|
||||
@ -2403,17 +2605,27 @@ void SourceView::RenderAsmLine( AsmLine& line, uint32_t ipcnt, uint32_t iptotal,
|
||||
inlineList++;
|
||||
}
|
||||
}
|
||||
const auto& stats = *worker.GetSymbolStats( symAddrParents );
|
||||
assert( !stats.parents.empty() );
|
||||
|
||||
if( m_font ) ImGui::PopFont();
|
||||
ImGui::BeginTooltip();
|
||||
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)" );
|
||||
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)" );
|
||||
}
|
||||
ImGui::EndTooltip();
|
||||
if( m_font ) ImGui::PushFont( m_font );
|
||||
|
||||
@ -2470,12 +2682,19 @@ void SourceView::RenderAsmLine( AsmLine& line, uint32_t ipcnt, uint32_t iptotal,
|
||||
m_asmSampleSelect.clear();
|
||||
m_asmGroupSelect = -1;
|
||||
}
|
||||
else if( ImGui::IsMouseClicked( 2 ) )
|
||||
else if( !stats.parents.empty() && ImGui::IsMouseClicked( 2 ) )
|
||||
{
|
||||
view.ShowSampleParents( symAddrParents );
|
||||
}
|
||||
}
|
||||
draw->AddLine( wpos + ImVec2( 0, 1 ), wpos + ImVec2( 0, ty-2 ), GetHotnessColor( ipcnt, ipmax ) );
|
||||
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 ) );
|
||||
}
|
||||
}
|
||||
ImGui::SameLine( 0, ty );
|
||||
}
|
||||
@ -2662,7 +2881,7 @@ void SourceView::RenderAsmLine( AsmLine& line, uint32_t ipcnt, uint32_t iptotal,
|
||||
const auto th4 = floor( ts.y / 4 );
|
||||
const auto& mjl = m_maxJumpLevel;
|
||||
const auto col = GetHsvColor( line.jumpAddr, 6 );
|
||||
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 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 );
|
||||
|
||||
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 );
|
||||
@ -3145,17 +3364,18 @@ void SourceView::SelectAsmLinesHover( uint32_t file, uint32_t line, const Worker
|
||||
}
|
||||
}
|
||||
|
||||
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 )
|
||||
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 )
|
||||
{
|
||||
const auto slzReady = worker.AreSourceLocationZonesReady();
|
||||
auto filename = m_source.filename();
|
||||
if( limitView )
|
||||
{
|
||||
auto vec = worker.GetSamplesForSymbol( addr );
|
||||
auto vec = worker.GetSamplesForSymbol( baseAddr );
|
||||
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 += end - it;
|
||||
iptotalAsm.local += end - it;
|
||||
while( it != end )
|
||||
{
|
||||
if( filename )
|
||||
@ -3172,16 +3392,16 @@ void SourceView::GatherIpStats( uint64_t addr, uint32_t& iptotalSrc, uint32_t& i
|
||||
auto sit = ipcountSrc.find( line );
|
||||
if( sit == ipcountSrc.end() )
|
||||
{
|
||||
ipcountSrc.emplace( line, 1 );
|
||||
if( ipmaxSrc < 1 ) ipmaxSrc = 1;
|
||||
ipcountSrc.emplace( line, AddrStat { 1, 0 } );
|
||||
if( ipmaxSrc.local < 1 ) ipmaxSrc.local = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto sum = sit->second + 1;
|
||||
sit->second = sum;
|
||||
if( ipmaxSrc < sum ) ipmaxSrc = sum;
|
||||
const auto sum = sit->second.local + 1;
|
||||
sit->second.local = sum;
|
||||
if( ipmaxSrc.local < sum ) ipmaxSrc.local = sum;
|
||||
}
|
||||
iptotalSrc++;
|
||||
iptotalSrc.local++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3191,14 +3411,14 @@ void SourceView::GatherIpStats( uint64_t addr, uint32_t& iptotalSrc, uint32_t& i
|
||||
auto sit = ipcountAsm.find( addr );
|
||||
if( sit == ipcountAsm.end() )
|
||||
{
|
||||
ipcountAsm.emplace( addr, 1 );
|
||||
if( ipmaxAsm < 1 ) ipmaxAsm = 1;
|
||||
ipcountAsm.emplace( addr, AddrStat{ 1, 0 } );
|
||||
if( ipmaxAsm.local < 1 ) ipmaxAsm.local = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto sum = sit->second + 1;
|
||||
sit->second = sum;
|
||||
if( ipmaxAsm < sum ) ipmaxAsm = sum;
|
||||
const auto sum = sit->second.local + 1;
|
||||
sit->second.local = sum;
|
||||
if( ipmaxAsm.local < sum ) ipmaxAsm.local = sum;
|
||||
}
|
||||
|
||||
++it;
|
||||
@ -3206,10 +3426,20 @@ void SourceView::GatherIpStats( uint64_t addr, uint32_t& iptotalSrc, uint32_t& i
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ipmap = worker.GetSymbolInstructionPointers( addr );
|
||||
auto ipmap = worker.GetSymbolInstructionPointers( baseAddr );
|
||||
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 );
|
||||
@ -3224,35 +3454,89 @@ void SourceView::GatherIpStats( uint64_t addr, uint32_t& iptotalSrc, uint32_t& i
|
||||
auto it = ipcountSrc.find( line );
|
||||
if( it == ipcountSrc.end() )
|
||||
{
|
||||
ipcountSrc.emplace( line, ip.second );
|
||||
if( ipmaxSrc < ip.second ) ipmaxSrc = ip.second;
|
||||
ipcountSrc.emplace( line, AddrStat{ ip.second, ccnt } );
|
||||
if( ipmaxSrc.local < ip.second ) ipmaxSrc.local = ip.second;
|
||||
if( ipmaxSrc.ext < ccnt ) ipmaxSrc.ext = ccnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto sum = it->second + ip.second;
|
||||
it->second = sum;
|
||||
if( ipmaxSrc < sum ) ipmaxSrc = sum;
|
||||
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;
|
||||
}
|
||||
iptotalSrc += ip.second;
|
||||
iptotalSrc.local += ip.second;
|
||||
iptotalSrc.ext += ccnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SourceView::CountAsmIpStats( uint64_t addr, const Worker& worker, bool limitView, const View& view )
|
||||
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 )
|
||||
{
|
||||
if( limitView )
|
||||
{
|
||||
auto vec = worker.GetSamplesForSymbol( addr );
|
||||
auto vec = worker.GetSamplesForSymbol( baseAddr );
|
||||
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;
|
||||
@ -3262,7 +3546,7 @@ uint32_t SourceView::CountAsmIpStats( uint64_t addr, const Worker& worker, bool
|
||||
else
|
||||
{
|
||||
uint32_t cnt = 0;
|
||||
auto ipmap = worker.GetSymbolInstructionPointers( addr );
|
||||
auto ipmap = worker.GetSymbolInstructionPointers( baseAddr );
|
||||
if( !ipmap ) return 0;
|
||||
for( auto& ip : *ipmap ) cnt += ip.second;
|
||||
return cnt;
|
||||
|
@ -100,6 +100,19 @@ 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*(*)();
|
||||
|
||||
@ -123,18 +136,19 @@ private:
|
||||
void RenderSimpleSourceView();
|
||||
void RenderSymbolView( 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 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 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 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 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 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 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 SelectMicroArchitecture( const char* moniker );
|
||||
|
||||
@ -169,6 +183,7 @@ private:
|
||||
uint8_t m_maxAsmBytes;
|
||||
bool m_atnt;
|
||||
uint64_t m_jumpPopupAddr;
|
||||
bool m_childCalls;
|
||||
|
||||
SourceContents m_source;
|
||||
SourceContents m_sourceTooltip;
|
||||
|
@ -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 );
|
||||
ImGui::Begin( tmp, &keepOpen, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse );
|
||||
TextCentered( ICON_FA_WIFI );
|
||||
ImGui::TextUnformatted( "Waiting for connection..." );
|
||||
DrawWaitingDots( s_time );
|
||||
@ -13801,6 +13801,15 @@ 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() )
|
||||
{
|
||||
|
@ -1830,12 +1830,29 @@ 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;
|
||||
} ) );
|
||||
@ -1983,6 +2000,18 @@ 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 );
|
||||
@ -2196,6 +2225,14 @@ 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
|
||||
@ -5565,11 +5602,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 );
|
||||
@ -5793,6 +5830,19 @@ 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 );
|
||||
|
@ -294,6 +294,7 @@ 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;
|
||||
@ -444,6 +445,10 @@ 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(); }
|
||||
@ -497,6 +502,7 @@ 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; }
|
||||
|
Loading…
Reference in New Issue
Block a user