mirror of
https://github.com/wolfpld/tracy.git
synced 2026-10-30 20:45:26 +00:00
Merge pull request #1469 from wolfpld/slomp/gpu-stats
GPU Zone Statistics
This commit is contained in:
@@ -2,6 +2,11 @@ Note: There is no guarantee that version mismatched client and server will
|
||||
be able to talk with each other. Network protocol breakages won't be listed
|
||||
here.
|
||||
|
||||
vx.xx.x (2026-xx-xx)
|
||||
--------------------
|
||||
|
||||
- Find zone window now works with GPU zones (histogram, statistics, self time).
|
||||
|
||||
v0.14.1 (2026-08-22)
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -4474,6 +4474,8 @@ Tracy gives you the ability to display an execution time histogram of all occurr
|
||||
|
||||
You start by entering a search query, which will be matched against known zone names (see section~\ref{markingzones} for information on the grouping of zone names). If the search found some results, you will be presented with a list of zones in the \emph{matched source locations} drop-down. The selected zone's graph is displayed on the \emph{histogram} drop-down, and also the matching zones are highlighted on the timeline view.
|
||||
|
||||
GPU zones are supported as well, using their GPU execution time. Zone grouping, the found-zones list, and call stack samples are available only for CPU zones.
|
||||
|
||||
Clicking the \RMB{}~right mouse button on the source file location will open the source file view window (if applicable, see section~\ref{sourceview}). If symbol data is available Tracy will try to match the instrumented zone name to a captured symbol. If this succeeds and there are no duplicate matches, the source file view will be accompanied by the disassembly of the code. Since this matching is not exact, in rare cases you may get the wrong data here. To just display the source code, press and hold the \keys{\ctrl} key while clicking the \RMB{}~right mouse button.
|
||||
|
||||
An example histogram is presented in figure~\ref{findzonehistogram}. Here you can see that the majority of zone calls (by count) are clustered in the 300~\si{\nano\second} group, closely followed by the 10~\si{\micro\second} cluster. There are some outliers at the 1~and~10~\si{\milli\second} marks, which can be ignored on most occasions, as these are single occurrences.
|
||||
|
||||
@@ -331,6 +331,7 @@ private:
|
||||
void DrawMessages();
|
||||
void DrawMessageLine( const MessageData& msg, bool hasCallstack, int& idx );
|
||||
void DrawFindZone();
|
||||
void DrawFindZoneCpuDetails( int16_t matchSrcloc );
|
||||
void AccumulationModeComboBox();
|
||||
void DrawStatistics();
|
||||
void DrawSamplesStatistics(Vector<SymList>& data, int64_t timeRange, uint64_t totalSamples, AccumulationMode accumulationMode);
|
||||
@@ -440,6 +441,7 @@ private:
|
||||
|
||||
void FindZones();
|
||||
void FindZonesCompare();
|
||||
bool IsGpuSourceLocation( int16_t srcloc ) const;
|
||||
|
||||
std::vector<MemoryPage> GetMemoryPages() const;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -721,7 +721,7 @@ void View::DrawStatistics()
|
||||
auto name = m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function );
|
||||
SmallColorBox( GetSrcLocColor( srcloc, 0 ) );
|
||||
ImGui::SameLine();
|
||||
if( m_statMode == 0 )
|
||||
if( m_statMode == 0 || m_statMode == 2 )
|
||||
{
|
||||
if( ImGui::Selectable( name, m_findZone.show && !m_findZone.match.empty() && m_findZone.match[m_findZone.selMatch] == v.srcloc, ImGuiSelectableFlags_SpanAllColumns ) )
|
||||
{
|
||||
|
||||
@@ -577,29 +577,7 @@ int64_t View::GetZoneChildTime( const ZoneEvent& zone )
|
||||
|
||||
int64_t View::GetZoneChildTime( const GpuEvent& zone )
|
||||
{
|
||||
int64_t time = 0;
|
||||
if( zone.Child() >= 0 )
|
||||
{
|
||||
auto& children = m_worker.GetGpuChildren( zone.Child() );
|
||||
if( children.is_magic() )
|
||||
{
|
||||
auto& vec = *(Vector<GpuEvent>*)&children;
|
||||
for( auto& v : vec )
|
||||
{
|
||||
const auto childSpan = std::max( int64_t( 0 ), v.GpuEnd() - v.GpuStart() );
|
||||
time += childSpan;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( auto& v : children )
|
||||
{
|
||||
const auto childSpan = std::max( int64_t( 0 ), v->GpuEnd() - v->GpuStart() );
|
||||
time += childSpan;
|
||||
}
|
||||
}
|
||||
}
|
||||
return time;
|
||||
return m_worker.GetGpuChildTime( zone );
|
||||
}
|
||||
|
||||
int64_t View::GetZoneChildTimeFast( const ZoneEvent& zone )
|
||||
|
||||
@@ -1489,6 +1489,19 @@ void View::DrawGpuInfoWindow()
|
||||
ShowZoneInfo( *parent, m_gpuInfoWindowThread );
|
||||
}
|
||||
}
|
||||
if( m_worker.AreGpuSourceLocationZonesReady() )
|
||||
{
|
||||
const auto sl = ev.SrcLoc();
|
||||
const auto& slz = m_worker.GetGpuZonesForSourceLocation( sl );
|
||||
if( !slz.zones.empty() )
|
||||
{
|
||||
ImGui::SameLine();
|
||||
if( ImGui::Button( ICON_FA_CHART_BAR " Statistics" ) )
|
||||
{
|
||||
m_findZone.ShowZone( sl, m_worker.GetString( srcloc.name.active ? srcloc.name : srcloc.function ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ev.callstack.Val() != 0 )
|
||||
{
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -2718,6 +2718,22 @@ const Worker::SourceLocationZones& Worker::GetZonesForSourceLocation( int16_t sr
|
||||
return it != m_data.sourceLocationZones.end() ? it->second : empty;
|
||||
}
|
||||
|
||||
Worker::GpuSourceLocationZones& Worker::GetGpuZonesForSourceLocation( int16_t srcloc )
|
||||
{
|
||||
assert( AreGpuSourceLocationZonesReady() );
|
||||
static GpuSourceLocationZones empty;
|
||||
auto it = m_data.gpuSourceLocationZones.find( srcloc );
|
||||
return it != m_data.gpuSourceLocationZones.end() ? it->second : empty;
|
||||
}
|
||||
|
||||
const Worker::GpuSourceLocationZones& Worker::GetGpuZonesForSourceLocation( int16_t srcloc ) const
|
||||
{
|
||||
assert( AreGpuSourceLocationZonesReady() );
|
||||
static const GpuSourceLocationZones empty;
|
||||
auto it = m_data.gpuSourceLocationZones.find( srcloc );
|
||||
return it != m_data.gpuSourceLocationZones.end() ? it->second : empty;
|
||||
}
|
||||
|
||||
const SymbolStats* Worker::GetSymbolStats( uint64_t symAddr ) const
|
||||
{
|
||||
assert( AreCallstackSamplesReady() );
|
||||
@@ -3582,6 +3598,32 @@ ThreadData* Worker::GetCurrentThreadData()
|
||||
return td;
|
||||
}
|
||||
|
||||
int64_t Worker::GetGpuChildTime( const GpuEvent& zone ) const
|
||||
{
|
||||
// Unresolved children (GpuEnd == -1, e.g. aborted trace) clamp to 0, overstating parent self-time.
|
||||
int64_t time = 0;
|
||||
if( zone.Child() >= 0 )
|
||||
{
|
||||
auto& children = GetGpuChildren( zone.Child() );
|
||||
if( children.is_magic() )
|
||||
{
|
||||
auto& vec = *(Vector<GpuEvent>*)&children;
|
||||
for( auto& v : vec )
|
||||
{
|
||||
time += std::max( int64_t( 0 ), v.GpuEnd() - v.GpuStart() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( auto& v : children )
|
||||
{
|
||||
time += std::max( int64_t( 0 ), v->GpuEnd() - v->GpuStart() );
|
||||
}
|
||||
}
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
Worker::SourceLocationZones* Worker::GetSourceLocationZonesReal( uint16_t srcloc )
|
||||
{
|
||||
@@ -3603,6 +3645,7 @@ Worker::GpuSourceLocationZones* Worker::GetGpuSourceLocationZonesReal( uint16_t
|
||||
m_data.gpuZonesLast.second = &it->second;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
#else
|
||||
uint64_t* Worker::GetSourceLocationZonesCntReal( uint16_t srcloc )
|
||||
{
|
||||
@@ -6200,6 +6243,10 @@ void Worker::ProcessGpuTime( const QueueGpuTime& ev )
|
||||
if( slz->max < timeSpan ) slz->max = timeSpan;
|
||||
slz->total += timeSpan;
|
||||
slz->sumSq += double( timeSpan ) * timeSpan;
|
||||
const auto selfSpan = timeSpan - GetGpuChildTime( *zone );
|
||||
if( slz->selfMin > selfSpan ) slz->selfMin = selfSpan;
|
||||
if( slz->selfMax < selfSpan ) slz->selfMax = selfSpan;
|
||||
slz->selfTotal += selfSpan;
|
||||
}
|
||||
#else
|
||||
CountZoneStatistics( zone );
|
||||
@@ -8118,6 +8165,10 @@ void Worker::ReconstructZoneStatistics( GpuEvent& zone, uint16_t thread )
|
||||
if( slz.max < timeSpan ) slz.max = timeSpan;
|
||||
slz.total += timeSpan;
|
||||
slz.sumSq += double( timeSpan ) * timeSpan;
|
||||
const auto selfSpan = timeSpan - GetGpuChildTime( zone );
|
||||
if( slz.selfMin > selfSpan ) slz.selfMin = selfSpan;
|
||||
if( slz.selfMax < selfSpan ) slz.selfMax = selfSpan;
|
||||
slz.selfTotal += selfSpan;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -224,6 +224,9 @@ private:
|
||||
int64_t max = std::numeric_limits<int64_t>::min();
|
||||
int64_t total = 0;
|
||||
double sumSq = 0;
|
||||
int64_t selfMin = std::numeric_limits<int64_t>::max();
|
||||
int64_t selfMax = std::numeric_limits<int64_t>::min();
|
||||
int64_t selfTotal = 0;
|
||||
};
|
||||
|
||||
struct CallstackFrameIdHash
|
||||
@@ -630,6 +633,7 @@ public:
|
||||
|
||||
tracy_force_inline const Vector<short_ptr<ZoneEvent>>& GetZoneChildren( int32_t idx ) const { return m_data.zoneChildren[idx]; }
|
||||
tracy_force_inline const Vector<short_ptr<GpuEvent>>& GetGpuChildren( int32_t idx ) const { return m_data.gpuChildren[idx]; }
|
||||
int64_t GetGpuChildTime( const GpuEvent& zone ) const;
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
tracy_force_inline const Vector<GhostZone>& GetGhostChildren( int32_t idx ) const { return m_data.ghostChildren[idx]; }
|
||||
tracy_force_inline const GhostKey& GetGhostFrame( const Int24& frame ) const { return m_data.ghostFrames[frame.Val()]; }
|
||||
@@ -645,6 +649,8 @@ public:
|
||||
#ifndef TRACY_NO_STATISTICS
|
||||
SourceLocationZones& GetZonesForSourceLocation( int16_t srcloc );
|
||||
const SourceLocationZones& GetZonesForSourceLocation( int16_t srcloc ) const;
|
||||
GpuSourceLocationZones& GetGpuZonesForSourceLocation( int16_t srcloc );
|
||||
const GpuSourceLocationZones& GetGpuZonesForSourceLocation( int16_t srcloc ) const;
|
||||
const unordered_flat_map<int16_t, SourceLocationZones>& GetSourceLocationZones() const { return m_data.sourceLocationZones; }
|
||||
const unordered_flat_map<int16_t, GpuSourceLocationZones>& GetGpuSourceLocationZones() const { return m_data.gpuSourceLocationZones; }
|
||||
bool AreSourceLocationZonesReady() const { return m_data.sourceLocationZonesReady; }
|
||||
|
||||
Reference in New Issue
Block a user