diff --git a/profiler/CMakeLists.txt b/profiler/CMakeLists.txt index 441cac06..7594a0f0 100644 --- a/profiler/CMakeLists.txt +++ b/profiler/CMakeLists.txt @@ -223,6 +223,7 @@ Embed(PROFILER_FILES TextGhostZones src/achievements/GhostZones.md TEXT) Embed(PROFILER_FILES TextGlobalSettings src/achievements/GlobalSettings.md TEXT) Embed(PROFILER_FILES TextGpu src/achievements/Gpu.md TEXT) Embed(PROFILER_FILES TextGpuStats src/achievements/GpuStats.md TEXT) +Embed(PROFILER_FILES TextHwCounters src/achievements/HwCounters.md TEXT) Embed(PROFILER_FILES TextInspectZone src/achievements/InspectZone.md TEXT) Embed(PROFILER_FILES TextInstrumentationIntro src/achievements/InstrumentationIntro.md TEXT) Embed(PROFILER_FILES TextInstrumentationStatistics src/achievements/InstrumentationStatistics.md TEXT) diff --git a/profiler/src/achievements/HwCounters.md b/profiler/src/achievements/HwCounters.md new file mode 100644 index 00000000..f4ccb0b1 --- /dev/null +++ b/profiler/src/achievements/HwCounters.md @@ -0,0 +1,9 @@ +# Hardware counters + +Call-stack sampling says which lines cost the most time. A hot line might be doing a lot of arithmetic, or it might be stalled waiting on memory. Performance counters track cycles, branch mispredictions, and cache misses per instruction. When the kernel makes them available, Tracy collects them by default on Linux (WSL2 included) and Android, with no need to run the application as an administrator ([hardware sampling](#hardwaresampling)). + +When the data is present, the toolbar of the [source view](#sourceview) shows a hardware row: a * Cost* dropdown re-ranks lines by a different counter, a * HW* switch adds IPC, branch, and cache columns, and an * Impact* switch changes what the branch and cache columns report. The dropdown starts at "Sample count", the software sampling you know. "Cycles" is its hardware-collected equivalent, and "Branch impact" and "Cache impact" weigh miss counts by how many events happened. + +The higher the IPC, the more work the core does per cycle, and a low value means it spends cycles waiting, usually on memory. The branch and cache columns report misprediction and cache miss rates. With Impact off, those columns show isolated rates, which mislead when the sample is small: 100% misses on ten accesses is nothing compared to 50% on two thousand. Numbers based on only a handful of samples are shown dimmed, because there is not enough data behind them to be trusted. + +Try opening the source view on a hot function and re-rank its lines by cycles. diff --git a/profiler/src/profiler/TracyAchievementData.cpp b/profiler/src/profiler/TracyAchievementData.cpp index 457af8b5..c6eaa55b 100644 --- a/profiler/src/profiler/TracyAchievementData.cpp +++ b/profiler/src/profiler/TracyAchievementData.cpp @@ -20,6 +20,7 @@ #include "data/TextGlobalSettings.hpp" #include "data/TextGpu.hpp" #include "data/TextGpuStats.hpp" +#include "data/TextHwCounters.hpp" #include "data/TextInspectZone.hpp" #include "data/TextInstrumentFrames.hpp" #include "data/TextInstrumentationIntro.hpp" @@ -184,10 +185,19 @@ AchievementItem ai_findZone = { .text = Unpack( TextFindZone ) }; +AchievementItem ai_hwCounters = { + .id = "hwCounters", + .name = "Hardware counters", + .text = Unpack( TextHwCounters ) +}; + +AchievementItem* ac_readAssemblyItems[] = { &ai_hwCounters, nullptr }; + AchievementItem ai_readAssembly = { .id = "readAssembly", .name = "Assembly required", - .text = Unpack( TextReadAssembly ) + .text = Unpack( TextReadAssembly ), + .items = ac_readAssemblyItems }; AchievementItem ai_compareTraces = { diff --git a/profiler/src/profiler/TracySourceView.cpp b/profiler/src/profiler/TracySourceView.cpp index 8668f685..9bdd88e2 100644 --- a/profiler/src/profiler/TracySourceView.cpp +++ b/profiler/src/profiler/TracySourceView.cpp @@ -1072,6 +1072,7 @@ void SourceView::RenderSymbolView( Worker& worker, View& view, WindowConstraints { m_cost = CostType::BranchMiss; } + if( s_config.achievements && m_cost != CostType::SampleCount ) view.Achieve( "hwCounters" ); } if( (CostType)idx == s_costSeparateAfter ) ImGui::Separator(); idx++;