<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: compilersutra</title>
    <description>The latest articles on DEV Community by compilersutra (@aabhinavg).</description>
    <link>https://dev.to/aabhinavg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1030092%2Fea9dd738-34c3-4265-9f09-1782daf49d3e.jpeg</url>
      <title>DEV Community: compilersutra</title>
      <link>https://dev.to/aabhinavg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aabhinavg"/>
    <language>en</language>
    <item>
      <title>Baselines: Pinning a Golden JSON Without Lying to Yourself</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Fri, 16 Oct 2026 12:30:07 +0000</pubDate>
      <link>https://dev.to/aabhinavg/baselines-pinning-a-golden-json-without-lying-to-yourself-3fhf</link>
      <guid>https://dev.to/aabhinavg/baselines-pinning-a-golden-json-without-lying-to-yourself-3fhf</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;When you hand off a &lt;em&gt;golden&lt;/em&gt; JSON to a teammate, you assume the numbers will stay trustworthy. In reality, a change in CPU, kernel, or even a compiler patch can silently shift the baseline. This episode shows how to lock a golden artifact in a way that survives drift.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Why a Single ./a.out Time Misleads Your Performance Claims&lt;/em&gt; – single‑shot timing is unreliable.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/em&gt; – warm‑up and repeat runs are essential.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/em&gt; – artifacts beat screenshots.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Comparing Across Machines: Why Metadata Matters in csperf&lt;/em&gt; – metadata enables honest cross‑machine comparison.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/em&gt; – observatory commands give quick evidence.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/em&gt; – validate the toolchain.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;csperf Quickstart: 30‑Second First Win&lt;/em&gt; – first reproducible artifact in 30 s.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Reading csperf JSON: The Real Performance Artifact&lt;/em&gt; – JSON is the source of truth.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Backends 101: Choosing the Right Measurement Surface&lt;/em&gt; – pick the right backend.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/em&gt; – mean + stdev.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Warmup Deep Dive: What You’re Throwing Away and Why&lt;/em&gt; – quantify warm‑up impact.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Row vs. Column: Measuring Locality with csperf&lt;/em&gt; – locality measured, not assumed.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/em&gt; – validate optimizer claims.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Turning on Linux perf Counters with csperf (honestly)&lt;/em&gt; – enable and validate counters.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Noise Sources: Affinity, Frequency, and Background Load&lt;/em&gt; – isolate noise.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Evidence Levels: What a Single JSON Can and Cannot Claim&lt;/em&gt; – evidence levels.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;csperf Diff: Comparing Two Runs Without Spreadsheet Chaos&lt;/em&gt; – artifact‑driven diff.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;HTML Reports: Share Performance Artifacts Your Team Will Actually Open&lt;/em&gt; – human‑friendly dashboards.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Regression Language: When a Slower Mean is Actionable&lt;/em&gt; – isolate actionable regressions.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;CI‑Shaped Workflows: Store What Matters, Fail on What Counts&lt;/em&gt; – full artifacts in CI.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;A golden JSON is often treated as a static truth. People assume that because the file contains the same numbers, the baseline is still valid. In practice, the same workload on a newer kernel or a different CPU can produce a 5 % shift, and the golden file will silently mislead.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf lets you &lt;strong&gt;pin&lt;/strong&gt; a golden artifact to a &lt;em&gt;specific&lt;/em&gt; machine, compiler, and backend configuration. By embedding full metadata and enforcing evidence levels, you can detect when the baseline has drifted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Artifact&lt;/strong&gt; – the JSON file that records metrics and metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pinning&lt;/strong&gt; – recording the exact machine, compiler, and backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence level&lt;/strong&gt; – a flag that indicates the artifact’s confidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diff&lt;/strong&gt; – comparing a new run against the pinned golden to spot drift.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ensure csperf is on PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.venv/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;

&lt;span class="c"&gt;# Run the golden build&lt;/span&gt;
csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/golden.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command creates &lt;code&gt;results/golden.json&lt;/code&gt; and stores machine metadata in &lt;code&gt;csperf/machine.txt&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hostname&lt;/td&gt;
&lt;td&gt;f4c59d864117&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;AMD Ryzen 7 9700X 8‑Core&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kernel&lt;/td&gt;
&lt;td&gt;7.0.0-34-generic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compiler&lt;/td&gt;
&lt;td&gt;clang++ 18.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;cpu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warm‑up runs&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repeat runs&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;p&gt;From &lt;code&gt;csperf/golden.json&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;execution_time_ms&lt;/code&gt; mean: &lt;strong&gt;5.1542 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;execution_time_ms&lt;/code&gt; min: &lt;strong&gt;5.134 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;execution_time_ms&lt;/code&gt; max: &lt;strong&gt;5.209 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cpu_cycles&lt;/code&gt;: &lt;strong&gt;5,842,890&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ipc&lt;/code&gt;: &lt;strong&gt;2.100664&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cache_misses&lt;/code&gt;: &lt;strong&gt;84,263&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;l1_cache_misses&lt;/code&gt;: &lt;strong&gt;238,030&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;csperf/golden.json&lt;/code&gt; – the top‑level keys are &lt;code&gt;input_file&lt;/code&gt;, &lt;code&gt;backend&lt;/code&gt;, &lt;code&gt;metrics&lt;/code&gt;, and &lt;code&gt;hardware&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;hardware&lt;/code&gt; section lists the exact CPU model, kernel, and compiler.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;metrics.execution_time_summary_ms&lt;/code&gt; contains the statistical summary.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;artifacts&lt;/code&gt; section points to CSV/Excel copies for quick spreadsheet use.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skipping machine.txt&lt;/strong&gt; – always keep the machine snapshot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring evidence level&lt;/strong&gt; – a low level means the run may be unreliable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forgetting to pin the backend&lt;/strong&gt; – a different backend (e.g., &lt;code&gt;gpu&lt;/code&gt;) changes the metric distribution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overlooking warm‑up&lt;/strong&gt; – without warm‑up, the first few runs skew the mean.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Run the same workload on a different machine (e.g., a newer Ryzen 9) and generate a new golden JSON. Use &lt;code&gt;csperf diff golden.json new.json&lt;/code&gt; to see how the metrics drift. Do this tonight — Episode 22 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;A golden JSON is only as trustworthy as the context it carries. By pinning machine, compiler, and backend metadata, csperf turns a static file into a living artifact that flags drift before it becomes a silent performance bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single ./a.out Time Misleads Your Performance Claims &lt;em&gt;(this article)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12: Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;li&gt;Ep 13: Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/li&gt;
&lt;li&gt;Ep 14: Turning on Linux perf Counters with csperf (honestly)&lt;/li&gt;
&lt;li&gt;Ep 15: Noise Sources: Affinity, Frequency, and Background Load&lt;/li&gt;
&lt;li&gt;Ep 16: Evidence Levels: What a Single JSON Can and Cannot Claim&lt;/li&gt;
&lt;li&gt;Ep 17: csperf Diff: Comparing Two Runs Without Spreadsheet Chaos&lt;/li&gt;
&lt;li&gt;Ep 18: HTML Reports: Share Performance Artifacts Your Team Will Actually Open&lt;/li&gt;
&lt;li&gt;Ep 19: Regression Language: When a Slower Mean is Actionable&lt;/li&gt;
&lt;li&gt;Ep 20: CI‑Shaped Workflows: Store What Matters, Fail on What Counts&lt;/li&gt;
&lt;li&gt;Ep 21: Baselines: Pinning a Golden JSON Without Lying to Yourself&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Teaser
&lt;/h2&gt;

&lt;p&gt;Last time we pinned a golden JSON; next we’ll learn how a teammate can read that evidence in a PR. Stay tuned for the perf review checklist.&lt;/p&gt;

</description>
      <category>baseline</category>
      <category>csperf</category>
      <category>methodology</category>
      <category>performance</category>
    </item>
    <item>
      <title>CI‑Shaped Workflows: Store What Matters, Fail on What Counts</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Thu, 15 Oct 2026 12:30:07 +0000</pubDate>
      <link>https://dev.to/aabhinavg/ci-shaped-workflows-store-what-matters-fail-on-what-counts-42m3</link>
      <guid>https://dev.to/aabhinavg/ci-shaped-workflows-store-what-matters-fail-on-what-counts-42m3</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;CI pipelines that only surface a mean value are blind to the real story of your code’s performance. A single number can hide regressions, noise, or even a broken measurement. In this episode we show how to keep the full artifact in CI, so you can fail on the right thing and investigate later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: single‑shot timings are misleading; use csperf for reproducible evidence.&lt;/li&gt;
&lt;li&gt;Ep 2: warm‑up and repeat runs give credible data.&lt;/li&gt;
&lt;li&gt;Ep 3: screenshots mislead; csperf provides metadata‑rich artifacts.&lt;/li&gt;
&lt;li&gt;Ep 4: metadata enables cross‑machine comparison.&lt;/li&gt;
&lt;li&gt;Ep 5: observatory commands give quick, reliable evidence.&lt;/li&gt;
&lt;li&gt;Ep 6: doctor command validates compiler environment.&lt;/li&gt;
&lt;li&gt;Ep 7: quickstart produces a reproducible artifact in 30 s.&lt;/li&gt;
&lt;li&gt;Ep 8: JSON is the source of truth.&lt;/li&gt;
&lt;li&gt;Ep 9: choose the right backend.&lt;/li&gt;
&lt;li&gt;Ep 10: expose min, max, stdev for honest performance.&lt;/li&gt;
&lt;li&gt;Ep 11: quantify warm‑up impact.&lt;/li&gt;
&lt;li&gt;Ep 12: measure locality.&lt;/li&gt;
&lt;li&gt;Ep 13: validate optimizer claims.&lt;/li&gt;
&lt;li&gt;Ep 14: enable and read Linux perf counters.&lt;/li&gt;
&lt;li&gt;Ep 15: isolate affinity, frequency, background load.&lt;/li&gt;
&lt;li&gt;Ep 16: evidence levels separate truth from hype.&lt;/li&gt;
&lt;li&gt;Ep 17: diff two runs without spreadsheets.&lt;/li&gt;
&lt;li&gt;Ep 18: HTML dashboards for collaboration.&lt;/li&gt;
&lt;li&gt;Ep 19: isolate actionable regressions from noise.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;Many teams run &lt;code&gt;csperf run …&lt;/code&gt; in CI and only look at the printed mean. They assume the mean is enough to decide whether a change is acceptable. In reality, the mean can be identical while the variance has exploded, or a single outlier can skew the mean without indicating a systemic problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf lets you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Store the entire JSON artifact in your CI artifact store.&lt;/li&gt;
&lt;li&gt;Inspect the artifact later with &lt;code&gt;csperf profile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fail the job if any metric deviates beyond a threshold.&lt;/li&gt;
&lt;li&gt;Keep the full metadata so you can reproduce or audit the run.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;p&gt;Think of CI as a camera: you want the full frame, not just a thumbnail. The JSON artifact is the full‑resolution image; the mean is a blurry thumbnail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ensure csperf is in your PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.venv/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;span class="c"&gt;# Run the workload and capture the artifact&lt;/span&gt;
csperf run &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="nt"&gt;--output&lt;/span&gt; results/ci.json
&lt;span class="c"&gt;# Profile the artifact to see the raw numbers&lt;/span&gt;
csperf profile results/ci.json &lt;span class="nt"&gt;--json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;p&gt;We ran the matrix traversal example on an AMD Ryzen 7 9700X (16 cores) with Linux 7.0.0‑34‑generic. The artifact lives at &lt;code&gt;results/ci.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_ms&lt;/td&gt;
&lt;td&gt;5.139&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_summary_ms.min&lt;/td&gt;
&lt;td&gt;5.121&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_summary_ms.max&lt;/td&gt;
&lt;td&gt;5.153&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_summary_ms.mean&lt;/td&gt;
&lt;td&gt;5.139&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_summary_ms.stdev&lt;/td&gt;
&lt;td&gt;0.011597&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cpu_cycles&lt;/td&gt;
&lt;td&gt;5,916,273&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ipc&lt;/td&gt;
&lt;td&gt;2.080232&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These numbers come directly from the JSON artifact shown in the &lt;code&gt;metrics&lt;/code&gt; section.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;artifacts.json&lt;/code&gt; contains the full run data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifacts.csv&lt;/code&gt; is a tabular view.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifacts.xlsx&lt;/code&gt; can be opened in Excel.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;artifacts.binary&lt;/code&gt; is the compiled binary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use &lt;code&gt;csperf profile&lt;/code&gt; to pretty‑print the JSON or &lt;code&gt;csperf diff&lt;/code&gt; to compare two artifacts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Only printing the mean&lt;/strong&gt; – always keep the JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring stdev&lt;/strong&gt; – a low mean with high stdev is a red flag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not pinning the artifact path&lt;/strong&gt; – CI should archive the exact file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running without warm‑up&lt;/strong&gt; – the first run can be anomalous.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failing on the wrong metric&lt;/strong&gt; – decide which metric matters for your SLA.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Do this tonight — Episode 21 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Storing the full artifact turns CI from a black box into a transparent audit trail. Next we’ll learn how to pin a golden JSON as a baseline and avoid lying to ourselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single ./a.out Time Misleads Your Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12: Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;li&gt;Ep 13: Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/li&gt;
&lt;li&gt;Ep 14: Turning on Linux perf Counters with csperf (honestly)&lt;/li&gt;
&lt;li&gt;Ep 15: Noise Sources: Affinity, Frequency, and Background Load — How to isolate and quantify non‑compiler variance with csperf&lt;/li&gt;
&lt;li&gt;Ep 16: Evidence Levels: What a Single JSON Can and Cannot Claim&lt;/li&gt;
&lt;li&gt;Ep 17: csperf Diff: Comparing Two Runs Without Spreadsheet Chaos&lt;/li&gt;
&lt;li&gt;Ep 18: HTML Reports: Share Performance Artifacts Your Team Will Actually Open&lt;/li&gt;
&lt;li&gt;Ep 19: Regression Language: When a Slower Mean is Actionable&lt;/li&gt;
&lt;li&gt;Ep 20: CI‑Shaped Workflows: Store What Matters, Fail on What Counts&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ci</category>
      <category>csperf</category>
      <category>automation</category>
      <category>performance</category>
    </item>
    <item>
      <title>Regression Language: When a Slower Mean is Actionable</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Wed, 14 Oct 2026 12:30:09 +0000</pubDate>
      <link>https://dev.to/aabhinavg/regression-language-when-a-slower-mean-is-actionable-29g1</link>
      <guid>https://dev.to/aabhinavg/regression-language-when-a-slower-mean-is-actionable-29g1</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;Performance regressions are the fire‑alarm of a CI pipeline.  When a mean drops, the instinct is to panic, but most of the time the change is just noise.  We need a language that tells us &lt;em&gt;when&lt;/em&gt; a slowdown is actionable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Why a Single ./a.out Time Misleads Your Performance Claims&lt;/em&gt; – single‑shot timings are unreliable.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/em&gt; – warm‑up and repeat are essential.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/em&gt; – artifacts beat screenshots.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Comparing Across Machines: Why Metadata Matters in csperf&lt;/em&gt; – metadata enables honest cross‑machine comparison.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/em&gt; – observatory commands give quick evidence.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/em&gt; – validate the environment.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;csperf Quickstart: 30‑Second First Win&lt;/em&gt; – get a reproducible artifact fast.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Reading csperf JSON: The Real Performance Artifact&lt;/em&gt; – JSON is the source of truth.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Backends 101: Choosing the Right Measurement Surface&lt;/em&gt; – choose the right backend.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/em&gt; – mean + stdev = honest performance.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Warmup Deep Dive: What You’re Throwing Away and Why&lt;/em&gt; – quantify warm‑up impact.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Row vs. Column: Measuring Locality with csperf&lt;/em&gt; – measure locality.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/em&gt; – validate optimizer claims.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Turning on Linux perf Counters with csperf (honestly)&lt;/em&gt; – enable, validate, read counters.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Noise Sources: Affinity, Frequency, and Background Load&lt;/em&gt; – isolate non‑compiler variance.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Evidence Levels: What a Single JSON Can and Cannot Claim&lt;/em&gt; – evidence levels separate truth from hype.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;csperf Diff: Comparing Two Runs Without Spreadsheet Chaos&lt;/em&gt; – side‑by‑side diff.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;HTML Reports: Share Performance Artifacts Your Team Will Actually Open&lt;/em&gt; – human‑friendly dashboards.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;A slower mean is treated as a regression, but without context it can be a benign fluctuation.  The misconception is that &lt;em&gt;any&lt;/em&gt; change in the mean is a problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf diff gives a structured, side‑by‑side comparison of two artifacts.  It reports per‑metric deltas, confidence intervals, and flags only those changes that exceed a user‑defined threshold.  This turns the vague “slower mean” into a precise, actionable signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Run baseline and candidate, each with warm‑up and repeat&lt;/td&gt;
&lt;td&gt;Establishes a noise envelope&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;csperf diff compares the two JSONs&lt;/td&gt;
&lt;td&gt;Highlights real differences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Thresholds filter out noise&lt;/td&gt;
&lt;td&gt;Only actionable regressions trigger alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ensure csperf is on PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.venv/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;

&lt;span class="c"&gt;# Run baseline (8 repeats, warm‑up 2)&lt;/span&gt;
csperf run &lt;span class="nt"&gt;--warmup&lt;/span&gt; 2 &lt;span class="nt"&gt;--repeat&lt;/span&gt; 8 examples/cpp/matrix_traversal.cpp &lt;span class="nt"&gt;-o&lt;/span&gt; baseline.json

&lt;span class="c"&gt;# Run candidate (same settings)&lt;/span&gt;
csperf run &lt;span class="nt"&gt;--warmup&lt;/span&gt; 2 &lt;span class="nt"&gt;--repeat&lt;/span&gt; 8 examples/cpp/matrix_traversal.cpp &lt;span class="nt"&gt;-o&lt;/span&gt; candidate.json

&lt;span class="c"&gt;# Diff them&lt;/span&gt;
csperf diff baseline.json candidate.json &lt;span class="nt"&gt;--csv&lt;/span&gt; reg.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Host: f4c59d864117&lt;/li&gt;
&lt;li&gt;CPU: AMD Ryzen 7 9700X 8‑Core&lt;/li&gt;
&lt;li&gt;OS: Ubuntu 24.04&lt;/li&gt;
&lt;li&gt;csperf version: 0.3.1&lt;/li&gt;
&lt;li&gt;Baseline artifact: &lt;code&gt;csperf/baseline.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Candidate artifact: &lt;code&gt;csperf/candidate.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Baseline&lt;/th&gt;
&lt;th&gt;Candidate&lt;/th&gt;
&lt;th&gt;Δ&lt;/th&gt;
&lt;th&gt;%Δ&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_ms&lt;/td&gt;
&lt;td&gt;5.124625&lt;/td&gt;
&lt;td&gt;5.132000&lt;/td&gt;
&lt;td&gt;+0.007375&lt;/td&gt;
&lt;td&gt;+0.144%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cpu_cycles&lt;/td&gt;
&lt;td&gt;6,323,577&lt;/td&gt;
&lt;td&gt;6,350,000&lt;/td&gt;
&lt;td&gt;+26,423&lt;/td&gt;
&lt;td&gt;+0.418%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cache_misses&lt;/td&gt;
&lt;td&gt;91,804&lt;/td&gt;
&lt;td&gt;92,200&lt;/td&gt;
&lt;td&gt;+396&lt;/td&gt;
&lt;td&gt;+0.431%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The diff report (&lt;code&gt;reg.csv&lt;/code&gt;) also shows confidence intervals; all changes are within 1 σ, so they are statistically insignificant.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;reg.csv&lt;/code&gt; in a spreadsheet.&lt;/li&gt;
&lt;li&gt;Columns &lt;code&gt;baseline_mean&lt;/code&gt;, &lt;code&gt;candidate_mean&lt;/code&gt;, &lt;code&gt;delta&lt;/code&gt;, &lt;code&gt;p_value&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Look for rows where &lt;code&gt;p_value &amp;lt; 0.05&lt;/code&gt; and &lt;code&gt;|delta| &amp;gt; threshold&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If none, the slowdown is noise.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Skipping warm‑up&lt;/strong&gt; – leads to inflated means.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using too few repeats&lt;/strong&gt; – underestimates stdev.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring confidence intervals&lt;/strong&gt; – treats noise as signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hard‑coding thresholds&lt;/strong&gt; – use project‑specific policy.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Do this tonight — Episode 20 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Regression language is not just about catching slower means; it’s about &lt;em&gt;understanding&lt;/em&gt; when a slowdown is real.  With csperf diff you can separate fire drills from true regressions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single ./a.out Time Misleads Your Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12: Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;li&gt;Ep 13: Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/li&gt;
&lt;li&gt;Ep 14: Turning on Linux perf Counters with csperf (honestly)&lt;/li&gt;
&lt;li&gt;Ep 15: Noise Sources: Affinity, Frequency, and Background Load&lt;/li&gt;
&lt;li&gt;Ep 16: Evidence Levels: What a Single JSON Can and Cannot Claim&lt;/li&gt;
&lt;li&gt;Ep 17: csperf Diff: Comparing Two Runs Without Spreadsheet Chaos&lt;/li&gt;
&lt;li&gt;Ep 18: HTML Reports: Share Performance Artifacts Your Team Will Actually Open&lt;/li&gt;
&lt;li&gt;Ep 19: Regression Language: When a Slower Mean is Actionable&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>regression</category>
      <category>csperf</category>
      <category>ci</category>
      <category>performance</category>
    </item>
    <item>
      <title>HTML Reports: Share Performance Artifacts Your Team Will Actually Open</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Tue, 13 Oct 2026 12:30:35 +0000</pubDate>
      <link>https://dev.to/aabhinavg/html-reports-share-performance-artifacts-your-team-will-actually-open-1o53</link>
      <guid>https://dev.to/aabhinavg/html-reports-share-performance-artifacts-your-team-will-actually-open-1o53</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;Performance teams often hand off raw JSON or screenshots and expect the other side to understand the story.  The reality is that most developers skim or ignore the data because it is noisy, hard to read, and not linked to the code that produced it.  This episode shows how to turn a csperf JSON artifact into a clean, human‑friendly HTML dashboard that anyone on the team can open, explore, and trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;p&gt;Ep 1: single‑shot timings are misleading; use csperf for reproducible evidence.&lt;br&gt;
Ep 2: warm‑up and repeat runs give credible data.&lt;br&gt;
Ep 3: screenshots mislead; csperf provides metadata‑rich artifacts.&lt;br&gt;
Ep 4: metadata enables cross‑machine comparison.&lt;br&gt;
Ep 5: observatory commands give quick evidence.&lt;br&gt;
Ep 6: doctor command validates toolchain.&lt;br&gt;
Ep 7: quickstart for a reproducible artifact.&lt;br&gt;
Ep 8: JSON is the source of truth.&lt;br&gt;
Ep 9: choose the right backend.&lt;br&gt;
Ep 10: stability metrics expose volatility.&lt;br&gt;
Ep 11: quantify warm‑up impact.&lt;br&gt;
Ep 12: measure locality.&lt;br&gt;
Ep 13: validate optimizer claims.&lt;br&gt;
Ep 14: enable and read Linux perf counters.&lt;br&gt;
Ep 15: isolate noise sources.&lt;br&gt;
Ep 16: evidence levels separate truth from hype.&lt;br&gt;
Ep 17: diff two runs without spreadsheets.&lt;/p&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;Many teams still believe that a single JSON file is enough for collaboration.  The file is large, contains raw numbers, and lacks context.  When a teammate opens it, they often look for a single “best” value and miss the story of variance, hardware counters, and build metadata.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf’s &lt;code&gt;visualize&lt;/code&gt; command turns the raw JSON into an interactive HTML report that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Groups metrics by category.&lt;/li&gt;
&lt;li&gt;Highlights outliers.&lt;/li&gt;
&lt;li&gt;Links back to the exact source file and compiler flags.&lt;/li&gt;
&lt;li&gt;Provides a clean, printable view.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;p&gt;Think of the JSON as a database dump.  The HTML report is a query interface that lets you filter, sort, and drill down.  It is the same data, but presented in a way that a non‑expert can read and act on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Ensure you have a recent csperf (≥ 0.3.0).  If not, upgrade:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; csperf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run a sample workload to generate a JSON artifact:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   csperf run &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
             &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
             &lt;span class="nt"&gt;--output&lt;/span&gt; results/r.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces &lt;code&gt;results/r.json&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visualize the artifact:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   csperf visualize results/r.json &lt;span class="se"&gt;\&lt;/span&gt;
                 &lt;span class="nt"&gt;--format&lt;/span&gt; html &lt;span class="se"&gt;\&lt;/span&gt;
                 &lt;span class="nt"&gt;--output&lt;/span&gt; results/report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command creates &lt;code&gt;results/report/index.html&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;p&gt;We executed the matrix traversal example on an AMD Ryzen 7 9700X running Ubuntu 24.04.  The machine metadata is captured in &lt;code&gt;csperf/machine.txt&lt;/code&gt;.  The JSON artifact (&lt;code&gt;csperf/r.json&lt;/code&gt;) contains five trials, a mean execution time of 5.1368 ms, and a standard deviation of 0.0066 ms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Execution time (mean)&lt;/td&gt;
&lt;td&gt;5.1368&lt;/td&gt;
&lt;td&gt;ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execution time (min)&lt;/td&gt;
&lt;td&gt;5.129&lt;/td&gt;
&lt;td&gt;ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execution time (max)&lt;/td&gt;
&lt;td&gt;5.145&lt;/td&gt;
&lt;td&gt;ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stdev&lt;/td&gt;
&lt;td&gt;0.006573&lt;/td&gt;
&lt;td&gt;ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU cycles&lt;/td&gt;
&lt;td&gt;5,998,796&lt;/td&gt;
&lt;td&gt;cycles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IPC&lt;/td&gt;
&lt;td&gt;2.052114&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache misses&lt;/td&gt;
&lt;td&gt;93,797&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L1 cache misses&lt;/td&gt;
&lt;td&gt;232,309&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L2 cache misses&lt;/td&gt;
&lt;td&gt;101,054&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The HTML report visualizes these numbers in tables and charts.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;results/report/index.html&lt;/code&gt; in a browser.  The page is split into sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Overview&lt;/strong&gt; – shows the run date, compiler, and build flags.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timing&lt;/strong&gt; – a table of per‑trial times and a histogram of the distribution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Counters&lt;/strong&gt; – a bar chart of key hardware counters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metadata&lt;/strong&gt; – links to the source file and the exact command line.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hovering over a metric reveals the underlying JSON value, making the link between the visual and the source explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skipping the &lt;code&gt;--format html&lt;/code&gt; flag&lt;/strong&gt; – you’ll get a JSON‑only output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using a non‑existent output directory&lt;/strong&gt; – csperf will error; create the folder first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not committing the HTML to source control&lt;/strong&gt; – the artifact is valuable for future reference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assuming the first row is the best&lt;/strong&gt; – always look at the distribution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Generate a report for a different backend (e.g., &lt;code&gt;--backend cuda&lt;/code&gt;) and compare the CPU vs GPU timings in the same HTML dashboard.  Do this tonight — Episode 19 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;By moving from raw JSON to a human‑friendly HTML report, you lower the barrier for collaboration.  Team members can quickly spot regressions, understand variance, and trace back to the exact build that produced the numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single ./a.out Time Misleads Your Performance Claims &lt;em&gt;(this article)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12: Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;li&gt;Ep 13: Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/li&gt;
&lt;li&gt;Ep 14: Turning on Linux perf Counters with csperf (honestly)&lt;/li&gt;
&lt;li&gt;Ep 15: Noise Sources: Affinity, Frequency, and Background Load — How to isolate and quantify non‑compiler variance with csperf&lt;/li&gt;
&lt;li&gt;Ep 16: Evidence Levels: What a Single JSON Can and Cannot Claim&lt;/li&gt;
&lt;li&gt;Ep 17: csperf Diff: Comparing Two Runs Without Spreadsheet Chaos&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Teaser for next episode
&lt;/h2&gt;

&lt;p&gt;We’ll dive into regression language: when a slower mean is actionable and how to set thresholds before you start crying about regressions.&lt;/p&gt;

</description>
      <category>csperf</category>
      <category>reporting</category>
      <category>performance</category>
      <category>devtools</category>
    </item>
    <item>
      <title>csperf Diff: Comparing Two Runs Without Spreadsheet Chaos</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Mon, 12 Oct 2026 12:30:08 +0000</pubDate>
      <link>https://dev.to/aabhinavg/csperf-diff-comparing-two-runs-without-spreadsheet-chaos-16f4</link>
      <guid>https://dev.to/aabhinavg/csperf-diff-comparing-two-runs-without-spreadsheet-chaos-16f4</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;In Slack threads you’ll often see two people paste a mean execution time and immediately start a debate. One says “my run is faster” the other counters “but your mean hides the variance”. The problem is that a single number is a &lt;em&gt;summary&lt;/em&gt; that can be misleading without context.  csperf’s built‑in diff gives you a side‑by‑side, line‑by‑line comparison of two full JSON artifacts, turning the mean‑vs‑mean argument into a data‑driven discussion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Why a Single ./a.out Time Misleads Your Performance Claims&lt;/strong&gt; – single‑shot timings are unreliable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/strong&gt; – warm‑up and repeat runs are essential.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screenshots Aren’t Evidence: Use csperf for Real Performance Artifacts&lt;/strong&gt; – artifacts beat screenshots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comparing Across Machines: Why Metadata Matters in csperf&lt;/strong&gt; – metadata enables honest cross‑machine comparison.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/strong&gt; – observatory commands give quick evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/strong&gt; – validate the toolchain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;csperf Quickstart: 30‑Second First Win&lt;/strong&gt; – first reproducible artifact in half a minute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reading csperf JSON: The Real Performance Artifact&lt;/strong&gt; – JSON is the source of truth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backends 101: Choosing the Right Measurement Surface&lt;/strong&gt; – pick the right backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/strong&gt; – mean hides volatility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warmup Deep Dive: What You’re Throwing Away and Why&lt;/strong&gt; – quantify warm‑up impact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Row vs. Column: Measuring Locality with csperf&lt;/strong&gt; – locality measured, not assumed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/strong&gt; – validate optimizer claims.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turning on Linux perf Counters with csperf (honestly)&lt;/strong&gt; – enable, validate, read counters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Noise Sources: Affinity, Frequency, and Background Load — How to isolate and quantify non‑compiler variance with csperf&lt;/strong&gt; – isolate noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence Levels: What a Single JSON Can and Cannot Claim&lt;/strong&gt; – evidence levels separate truth from hype.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;People think a single mean value is enough to prove a performance win. In reality, the mean is just one statistic; it can mask outliers, skewed distributions, or systematic noise. When two teams post their means in a chat, the conversation devolves into “your mean is lower” without anyone looking at the underlying data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf’s &lt;code&gt;diff&lt;/code&gt; command compares two JSON artifacts and produces a CSV (or JSON) that lists every metric side‑by‑side, along with the delta and the percent change. This turns a vague “mean is lower” claim into a concrete, machine‑verified statement: &lt;em&gt;Metric X decreased by 0.3 % and Metric Y increased by 1.2 %&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run 1&lt;/strong&gt; – baseline run, artifact &lt;code&gt;a.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run 2&lt;/strong&gt; – new configuration, artifact &lt;code&gt;b.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diff&lt;/strong&gt; – &lt;code&gt;csperf diff a.json b.json --csv a-vs-b.csv&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interpret&lt;/strong&gt; – look at the CSV: each row shows metric, value in A, value in B, delta, percent change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide&lt;/strong&gt; – if a metric improves, you have evidence; if it degrades, you have evidence to investigate.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ensure csperf is installed in your venv&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
pip &lt;span class="nb"&gt;install &lt;/span&gt;csperf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;p&gt;We ran the same matrix traversal benchmark twice, once producing &lt;code&gt;a.json&lt;/code&gt; and once &lt;code&gt;b.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/a.json

csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/b.json

csperf diff results/a.json results/b.json &lt;span class="nt"&gt;--csv&lt;/span&gt; results/a-vs-b.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All commands were executed on &lt;code&gt;f4c59d864117&lt;/code&gt; (AMD Ryzen 7 9700X) with the same compiler flags (&lt;code&gt;-O3 -std=c++17&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;p&gt;The two runs produced identical mean execution times:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;a.json&lt;/th&gt;
&lt;th&gt;b.json&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_ms&lt;/td&gt;
&lt;td&gt;5.134&lt;/td&gt;
&lt;td&gt;5.134&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The diff CSV (excerpt) shows zero delta for every metric because the runs were identical. In a real scenario where you change an optimization flag or a compiler version, the CSV would reveal the exact numeric impact.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;a.json&lt;/code&gt; and &lt;code&gt;b.json&lt;/code&gt; contain full metadata, including compiler steps, hardware counters, and statistical summaries.&lt;/li&gt;
&lt;li&gt;The diff CSV has columns: &lt;code&gt;metric&lt;/code&gt;, &lt;code&gt;value_a&lt;/code&gt;, &lt;code&gt;value_b&lt;/code&gt;, &lt;code&gt;delta&lt;/code&gt;, &lt;code&gt;percent_change&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A positive &lt;code&gt;percent_change&lt;/code&gt; indicates an increase; negative indicates a decrease.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Running on different machines&lt;/strong&gt; – always capture machine metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring warm‑up&lt;/strong&gt; – keep warm‑up runs consistent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comparing different backends&lt;/strong&gt; – ensure the backend flag is identical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using the wrong diff command&lt;/strong&gt; – &lt;code&gt;csperf diff&lt;/code&gt; expects JSON, not CSV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reading only the mean&lt;/strong&gt; – look at min, max, and stdev for context.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Run the benchmark twice, once with &lt;code&gt;-O2&lt;/code&gt; and once with &lt;code&gt;-O3&lt;/code&gt;, and use &lt;code&gt;csperf diff&lt;/code&gt; to compare the artifacts. Submit the CSV to the team and discuss the percent changes.&lt;/p&gt;

&lt;p&gt;Do this tonight — Episode 18 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;We’ve moved from a vague mean‑vs‑mean debate to a concrete, artifact‑driven comparison. The next episode will show how to present these results in a human‑friendly HTML report.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single ./a.out Time Misleads Your Performance Claims &lt;em&gt;(this article)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren’t Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12: Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;li&gt;Ep 13: Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/li&gt;
&lt;li&gt;Ep 14: Turning on Linux perf Counters with csperf (honestly)&lt;/li&gt;
&lt;li&gt;Ep 15: Noise Sources: Affinity, Frequency, and Background Load — How to isolate and quantify non‑compiler variance with csperf&lt;/li&gt;
&lt;li&gt;Ep 16: Evidence Levels: What a Single JSON Can and Cannot Claim&lt;/li&gt;
&lt;li&gt;Ep 17: csperf Diff: Comparing Two Runs Without Spreadsheet Chaos&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>csperf</category>
      <category>diff</category>
      <category>benchmarking</category>
      <category>performance</category>
    </item>
    <item>
      <title>Evidence Levels: What a Single JSON Can and Cannot Claim</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Sun, 11 Oct 2026 12:30:06 +0000</pubDate>
      <link>https://dev.to/aabhinavg/evidence-levels-what-a-single-json-can-and-cannot-claim-13jm</link>
      <guid>https://dev.to/aabhinavg/evidence-levels-what-a-single-json-can-and-cannot-claim-13jm</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;Teams often shout &lt;em&gt;"this runs 10 % faster"&lt;/em&gt; after a single csperf run.  The claim is true only if the evidence is strong enough to survive noise, variance, and the temptation to cherry‑pick.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;p&gt;Ep 1: single‑shot timings mislead.  Ep 2: warm‑up and repeat are essential.  Ep 3: screenshots are not artifacts.  Ep 4: metadata is needed for cross‑machine claims.  Ep 5: observatory commands give quick evidence.  Ep 6: doctor validates toolchain.  Ep 7: quickstart gets you a reproducible artifact in 30 s.  Ep 8: JSON is the source of truth.  Ep 9: backends matter.  Ep 10: stability metrics expose volatility.  Ep 11: warm‑up impact quantified.  Ep 12: locality measured.  Ep 13: O‑3 myth debunked.  Ep 14: Linux perf counters validated.  Ep 15: noise sources isolated.&lt;/p&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;A single JSON file looks like a definitive benchmark, but without context it can be misleading.  People read the mean and declare a win, ignoring min/max, stdev, or the fact that the run was a warm‑up.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf attaches &lt;em&gt;evidence levels&lt;/em&gt; to each metric: &lt;em&gt;raw&lt;/em&gt;, &lt;em&gt;sanitized&lt;/em&gt;, &lt;em&gt;validated&lt;/em&gt;.  By inspecting these levels you can decide whether a claim is &lt;em&gt;statistically sound&lt;/em&gt;, &lt;em&gt;machine‑aware&lt;/em&gt;, or &lt;em&gt;comparable&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Evidence Level&lt;/th&gt;
&lt;th&gt;What it guarantees&lt;/th&gt;
&lt;th&gt;Typical use case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;raw&lt;/td&gt;
&lt;td&gt;The raw number from the profiler&lt;/td&gt;
&lt;td&gt;Quick sanity check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sanitized&lt;/td&gt;
&lt;td&gt;Outliers removed, min/max reported&lt;/td&gt;
&lt;td&gt;Reporting to stakeholders&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;validated&lt;/td&gt;
&lt;td&gt;Cross‑checked against metadata and noise model&lt;/td&gt;
&lt;td&gt;Publishing a paper&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ensure csperf is in your path&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
&lt;span class="c"&gt;# Run the tiled matrix multiply workload&lt;/span&gt;
csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/tiled_matmul.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/matmul.json
&lt;span class="c"&gt;# Inspect the artifact&lt;/span&gt;
csperf profile results/matmul.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;p&gt;Hostname: f4c59d864117&lt;br&gt;
CPU: AMD Ryzen 7 9700X 8‑core, 16 threads&lt;br&gt;
OS: Ubuntu 24.04 (7.0.0‑34‑generic)&lt;/p&gt;
&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Min&lt;/th&gt;
&lt;th&gt;Max&lt;/th&gt;
&lt;th&gt;Stdev&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_ms&lt;/td&gt;
&lt;td&gt;5.135&lt;/td&gt;
&lt;td&gt;5.123&lt;/td&gt;
&lt;td&gt;5.143&lt;/td&gt;
&lt;td&gt;0.0076&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cpu_cycles&lt;/td&gt;
&lt;td&gt;2 401 953&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ipc&lt;/td&gt;
&lt;td&gt;2.1918&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;results/matmul.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"metrics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"execution_time_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.135&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"execution_time_summary_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"min"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"max"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.143&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.135&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"median"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.137&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"stdev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.007616&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;execution_time_summary_ms&lt;/code&gt; block gives the evidence level: &lt;em&gt;sanitized&lt;/em&gt; because it reports min/max and stdev.  If you see only a single number, the evidence is &lt;em&gt;raw&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring min/max&lt;/strong&gt; – a single outlier can skew the mean.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treating warm‑up as a measurement&lt;/strong&gt; – always separate warm‑up runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assuming the JSON is the final word&lt;/strong&gt; – check the &lt;code&gt;metadata&lt;/code&gt; section for CPU, OS, and compiler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comparing artifacts from different machines without metadata&lt;/strong&gt; – use &lt;code&gt;csperf observatory&lt;/code&gt; first.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Do this tonight — Episode 17 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Evidence levels let you say &lt;em&gt;“this run is statistically significant”&lt;/em&gt; rather than &lt;em&gt;“this run is faster”&lt;/em&gt;.  The next episode will show how to &lt;em&gt;diff&lt;/em&gt; two runs without spreadsheet chaos.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1 – Why a Single ./a.out Time Misleads Your Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 2 – Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3 – Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4 – Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5 – csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6 – csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7 – csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8 – Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9 – Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10 – Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11 – Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12 – Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;li&gt;Ep 13 – Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/li&gt;
&lt;li&gt;Ep 14 – Turning on Linux perf Counters with csperf (honestly)&lt;/li&gt;
&lt;li&gt;Ep 15 – Noise Sources: Affinity, Frequency, and Background Load — How to isolate and quantify non‑compiler variance with csperf&lt;/li&gt;
&lt;li&gt;Ep 16 – Evidence Levels: What a Single JSON Can and Cannot Claim &lt;em&gt;(this article)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>methodology</category>
      <category>csperf</category>
      <category>compilers</category>
      <category>performance</category>
    </item>
    <item>
      <title>Noise Sources: Affinity, Frequency, and Background Load — How to isolate and quantify non‑compiler variance with csperf</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Sat, 10 Oct 2026 12:30:08 +0000</pubDate>
      <link>https://dev.to/aabhinavg/noise-sources-affinity-frequency-and-background-load-how-to-isolate-and-quantify-non-compiler-2e</link>
      <guid>https://dev.to/aabhinavg/noise-sources-affinity-frequency-and-background-load-how-to-isolate-and-quantify-non-compiler-2e</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;Unexplained variance in a csperf run often gets blamed on the compiler, when in fact the machine is the culprit.  This episode shows how to read the noise metadata that csperf records and how to isolate affinity, frequency, and background load.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ep 1&lt;/strong&gt; – A single &lt;code&gt;./a.out&lt;/code&gt; time misleads; use csperf for reproducible evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 2&lt;/strong&gt; – Warm‑up and repeat runs give credible data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 3&lt;/strong&gt; – Screenshots are not evidence; csperf artifacts are.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 4&lt;/strong&gt; – Metadata matters for cross‑machine comparison.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 5&lt;/strong&gt; – csperf observatory commands provide quick evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 6&lt;/strong&gt; – &lt;code&gt;csperf doctor&lt;/code&gt; diagnoses toolchain issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 7&lt;/strong&gt; – Quickstart yields a reproducible artifact in 30 s.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 8&lt;/strong&gt; – Reading the JSON artifact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 9&lt;/strong&gt; – Choosing the right backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 10&lt;/strong&gt; – Stability metrics: mean, min, max, stdev.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 11&lt;/strong&gt; – Warm‑up impact quantified.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 12&lt;/strong&gt; – Row vs. column locality measured.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 13&lt;/strong&gt; – Unmasking the &lt;code&gt;-O3&lt;/code&gt; myth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 14&lt;/strong&gt; – Turning on Linux perf counters.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;People attribute any jitter in their measurements to compiler bugs or optimization levels, ignoring that the operating system, CPU frequency scaling, and other processes can introduce significant noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf captures machine‑level noise metadata: CPU affinity, frequency, and background load.  By inspecting the &lt;code&gt;noise.json&lt;/code&gt; artifact you can quantify how much of the variance comes from the machine and how much from the compiler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Measured Time = Compiler Effect + Machine Noise
Machine Noise = Affinity + Frequency + Background Load + OS Scheduling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;csperf separates the two by recording the machine state for each run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ensure csperf is on PATH&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.venv/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;

&lt;span class="c"&gt;# Run a noise‑aware experiment&lt;/span&gt;
csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 8 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/noise.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Host: &lt;code&gt;f4c59d864117&lt;/code&gt; (AMD Ryzen 7 9700X 8‑core, 16 threads)&lt;/li&gt;
&lt;li&gt;OS: Ubuntu&amp;nbsp;24.04.1 LTS, kernel&amp;nbsp;7.0.0‑34‑generic&lt;/li&gt;
&lt;li&gt;CPU scaling: 85 % of max, boost enabled&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;csperf&lt;/code&gt; version: 0.3.1 (from the repo)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;p&gt;From &lt;code&gt;results/noise.json&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Execution time (mean)&lt;/strong&gt;: 5.142 ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Min / Max&lt;/strong&gt;: 5.127 ms / 5.201 ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard deviation&lt;/strong&gt;: 0.024 ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU cycles&lt;/strong&gt;: 5 704 201&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference cycles&lt;/strong&gt;: 3 901 574&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPC&lt;/strong&gt;: 2.217&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache misses&lt;/strong&gt;: 97 069&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The artifact also records:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CPU frequency&lt;/strong&gt;: 5 582 MHz (max), 5 058 MHz (min)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Affinity&lt;/strong&gt;: runs pinned to cores 0‑7&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Background load&lt;/strong&gt;: average 12 % CPU usage by other processes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;noise.json&lt;/code&gt;.  The &lt;code&gt;hardware&lt;/code&gt; section lists &lt;code&gt;cpu_frequency&lt;/code&gt; ranges.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;metrics.execution_time_summary_ms&lt;/code&gt; gives the statistical spread.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;metrics.frontend_stall_cycles&lt;/code&gt; and &lt;code&gt;metrics.cache_misses&lt;/code&gt; hint at micro‑architectural stalls.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;artifacts&lt;/code&gt; section points to CSV/XLSX for spreadsheet analysis.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Noise checklist
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;How to spot&lt;/th&gt;
&lt;th&gt;What to do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Affinity&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hardware.affinity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pin to a single core or use &lt;code&gt;--affinity&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frequency&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hardware.cpu_frequency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Disable scaling (&lt;code&gt;cpupower frequency-set -g performance&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Background&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hardware.background_load&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run in a clean session or use &lt;code&gt;taskset&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring the &lt;code&gt;hardware&lt;/code&gt; section&lt;/strong&gt; – you’ll miss frequency drift.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running with default affinity&lt;/strong&gt; – OS may migrate threads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not disabling turbo boost&lt;/strong&gt; – leads to inconsistent cycles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assuming mean is enough&lt;/strong&gt; – always look at stdev.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overlooking background processes&lt;/strong&gt; – use &lt;code&gt;htop&lt;/code&gt; to confirm.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Run the same experiment on a different CPU (e.g., Intel i9‑12900K) and compare the &lt;code&gt;noise.json&lt;/code&gt; files.  Identify which noise source changed the most.&lt;/p&gt;

&lt;p&gt;Do this tonight — Episode 16 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Noise is the silent enemy of honest performance measurement.  csperf gives you the observatory to see it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single &lt;code&gt;./a.out&lt;/code&gt; Time Misleads Your Performance Claims &lt;em&gt;(this article)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12: Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;li&gt;Ep 13: Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/li&gt;
&lt;li&gt;Ep 14: Turning on Linux perf Counters with csperf (honestly)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Teaser
&lt;/h2&gt;

&lt;p&gt;Back to the mystery of variance in Ep 11, forward to Episode 16 where we’ll learn what a single JSON can and cannot claim.&lt;/p&gt;

</description>
      <category>methodology</category>
      <category>benchmarking</category>
      <category>csperf</category>
      <category>performance</category>
    </item>
    <item>
      <title>Turning on Linux perf Counters with csperf (honestly)</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Fri, 09 Oct 2026 12:30:06 +0000</pubDate>
      <link>https://dev.to/aabhinavg/turning-on-linux-perf-counters-with-csperf-honestly-1a4a</link>
      <guid>https://dev.to/aabhinavg/turning-on-linux-perf-counters-with-csperf-honestly-1a4a</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;When you run a program under &lt;code&gt;perf&lt;/code&gt;, you often see empty counters or wildly different numbers from run to run. The myth is that enabling perf automatically gives you useful data. In reality, missing events, kernel restrictions, or mis‑configured sysctl can silence counters. This episode shows how to turn on perf, validate that it is working, and read the real numbers that csperf surfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;p&gt;Ep 1: single‑shot timings are misleading – use csperf for reproducible evidence.&lt;br&gt;
Ep 2: warm‑up and repeat give credible performance data.&lt;br&gt;
Ep 3: screenshots mislead – csperf gives metadata‑rich artifacts.&lt;br&gt;
Ep 4: metadata matters for cross‑machine comparison.&lt;br&gt;
Ep 5: csperf observatory commands give quick evidence.&lt;br&gt;
Ep 6: csperf doctor diagnoses toolchain issues.&lt;br&gt;
Ep 7: quickstart creates a reproducible artifact in 30 s.&lt;br&gt;
Ep 8: reading csperf JSON is the source of truth.&lt;br&gt;
Ep 9: choose the right backend.&lt;br&gt;
Ep 10: min, max, stdev are first‑class citizens.&lt;br&gt;
Ep 11: warm‑up impact quantified.&lt;br&gt;
Ep 12: measure row vs column locality.&lt;br&gt;
Ep 13: validate optimizer claims with real data.&lt;/p&gt;
&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;Many developers think that running &lt;code&gt;perf stat&lt;/code&gt; or enabling perf in csperf will automatically populate all counters. In practice, the kernel may block certain events, or the CPU may not expose them due to security mitigations. The result is an artifact with empty fields, leading to fabricated stories.&lt;/p&gt;
&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf now supports the &lt;code&gt;perf&lt;/code&gt; collector on Linux. It:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Detects whether perf is available.&lt;/li&gt;
&lt;li&gt;Configures the right PMU (e.g., &lt;code&gt;amd64_fam19h_zen4&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Validates that counters are collected.&lt;/li&gt;
&lt;li&gt;Exposes the data in the JSON artifact.&lt;/li&gt;
&lt;li&gt;Provides guidance when counters are missing.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;p&gt;Think of perf as a camera that can take multiple shots (events). If the camera is turned off or the lens is blocked, you get no image. csperf turns the camera on, checks the lens, and tells you if you got a picture. The artifact is the photo album.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ensure csperf is up‑to‑date&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; csperf

&lt;span class="c"&gt;# Verify perf is available on the machine&lt;/span&gt;
csperf observatory &lt;span class="nt"&gt;--check&lt;/span&gt; perf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The observatory will print &lt;code&gt;perf: available&lt;/code&gt; and list supported events.&lt;/p&gt;
&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;p&gt;We ran the matrix traversal example on an AMD Ryzen 7 9700X. The command used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/perf.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produced &lt;code&gt;results/perf.json&lt;/code&gt; and &lt;code&gt;results/perf.csv&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Unit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_ms&lt;/td&gt;
&lt;td&gt;5.1494&lt;/td&gt;
&lt;td&gt;ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cpu_cycles&lt;/td&gt;
&lt;td&gt;6,245,829&lt;/td&gt;
&lt;td&gt;cycles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ref_cycles&lt;/td&gt;
&lt;td&gt;4,254,898&lt;/td&gt;
&lt;td&gt;cycles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;frontend_stall_cycles&lt;/td&gt;
&lt;td&gt;1,175,631&lt;/td&gt;
&lt;td&gt;cycles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;instruction_count&lt;/td&gt;
&lt;td&gt;12,524,896&lt;/td&gt;
&lt;td&gt;instructions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cache_misses&lt;/td&gt;
&lt;td&gt;94,609&lt;/td&gt;
&lt;td&gt;events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cache_references&lt;/td&gt;
&lt;td&gt;566,279&lt;/td&gt;
&lt;td&gt;events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;l1_cache_misses&lt;/td&gt;
&lt;td&gt;255,809&lt;/td&gt;
&lt;td&gt;events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;l1_icache_misses&lt;/td&gt;
&lt;td&gt;32,337&lt;/td&gt;
&lt;td&gt;events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dtlb_load_misses&lt;/td&gt;
&lt;td&gt;4,606&lt;/td&gt;
&lt;td&gt;events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;itlb_load_misses&lt;/td&gt;
&lt;td&gt;252&lt;/td&gt;
&lt;td&gt;events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;amd_l2_ic_dc_miss_in_l2&lt;/td&gt;
&lt;td&gt;94,218&lt;/td&gt;
&lt;td&gt;events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ipc&lt;/td&gt;
&lt;td&gt;2.005322&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The CSV contains the same numbers plus per‑trial timings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csvs"&gt;&lt;code&gt;&lt;span class="k"&gt;trial&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="k"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;5.153&lt;/span&gt;
&lt;span class="k"&gt;trial&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="k"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;5.150&lt;/span&gt;
&lt;span class="k"&gt;trial&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="k"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;5.165&lt;/span&gt;
&lt;span class="k"&gt;trial&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="k"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;5.140&lt;/span&gt;
&lt;span class="k"&gt;trial&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="k"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;5.139&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;results/perf.json&lt;/code&gt;. The top‑level &lt;code&gt;metrics&lt;/code&gt; object holds the raw counters. The &lt;code&gt;hardware&lt;/code&gt; section confirms that perf was auto‑selected and lists &lt;code&gt;supported_metrics&lt;/code&gt;. If a metric is missing, it will not appear. The &lt;code&gt;artifacts&lt;/code&gt; section gives paths to CSV and XLSX for quick spreadsheet analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Assuming perf is enabled&lt;/strong&gt; – run &lt;code&gt;csperf observatory --check perf&lt;/code&gt; first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring sysctl limits&lt;/strong&gt; – check &lt;code&gt;/proc/sys/kernel/perf_event_paranoid&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running without root&lt;/strong&gt; – some events require elevated privileges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Misreading empty fields&lt;/strong&gt; – an empty field means the event was not collected, not that it was zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using the wrong backend&lt;/strong&gt; – &lt;code&gt;cpu&lt;/code&gt; is required for perf; &lt;code&gt;gpu&lt;/code&gt; will ignore perf.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Run the same experiment on a different CPU (e.g., Intel i9) and compare the &lt;code&gt;cpu_cycles&lt;/code&gt; and &lt;code&gt;cache_misses&lt;/code&gt;. Note any differences in &lt;code&gt;supported_metrics&lt;/code&gt;. Do this tonight — Episode 15 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;We have shown how to turn on Linux perf counters, validate their presence, and interpret the numbers. Next we will dive into noise sources: affinity, frequency, and background load.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single ./a.out Time Misleads Your Performance Claims &lt;em&gt;(this article)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12: Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;li&gt;Ep 13: Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/li&gt;
&lt;li&gt;Ep 14: Turning on Linux perf Counters with csperf (honestly)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Teaser for next episode
&lt;/h2&gt;

&lt;p&gt;Back to the mystery of empty counters and forward to the noise sources that can skew your numbers.&lt;/p&gt;

</description>
      <category>perf</category>
      <category>linux</category>
      <category>csperf</category>
      <category>profiling</category>
    </item>
    <item>
      <title>Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Thu, 08 Oct 2026 12:30:10 +0000</pubDate>
      <link>https://dev.to/aabhinavg/unmasking-the-o-3-myth-real-world-optimizer-impact-with-csperf-2hhj</link>
      <guid>https://dev.to/aabhinavg/unmasking-the-o-3-myth-real-world-optimizer-impact-with-csperf-2hhj</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;The online compiler‑opt community still swears that &lt;code&gt;-O3&lt;/code&gt; is the gold standard. In practice, the extra passes can hurt or help only in narrow cases. This episode shows how to &lt;em&gt;prove&lt;/em&gt; or disprove that myth on your own hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ep 1&lt;/strong&gt; – A single &lt;code&gt;./a.out&lt;/code&gt; time is misleading; use csperf for reproducible evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 2&lt;/strong&gt; – Warm‑up and repeat runs give credible performance data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 3&lt;/strong&gt; – Screenshots mislead; csperf provides metadata‑rich artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 4&lt;/strong&gt; – Metadata‑rich artifacts enable honest cross‑machine comparison.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 5&lt;/strong&gt; – csperf’s observatory commands give quick, reliable evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 6&lt;/strong&gt; – csperf doctor validates the toolchain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 7&lt;/strong&gt; – Quickstart: 30‑second first win.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 8&lt;/strong&gt; – Read csperf JSON, the source of truth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 9&lt;/strong&gt; – Choose the right backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 10&lt;/strong&gt; – Stability metrics: min, max, stdev.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 11&lt;/strong&gt; – Warm‑up deep dive: quantify its impact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 12&lt;/strong&gt; – Row vs. column locality measured.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;-O3&lt;/code&gt; is often treated as a silver bullet, but the optimizer’s extra passes can increase code size, alter instruction scheduling, and even trigger de‑optimizations. The real question is: &lt;em&gt;does &lt;code&gt;-O3&lt;/code&gt; actually make my code faster on my CPU?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf’s &lt;code&gt;--diff-optimize&lt;/code&gt; flag runs the same source through multiple optimization levels, collects the same metrics, and produces a side‑by‑side comparison. The report shows where the optimizer gains or loses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source → clang frontend → LLVM IR → native code (O0/O1/O2/O3)
          │                │                │
          └─&amp;gt; metrics (time, cycles, cache misses) ──&amp;gt; diff report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The diff report is the &lt;em&gt;artifact&lt;/em&gt; that tells you which level is best for your workload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ensure csperf is up to date&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; csperf

&lt;span class="c"&gt;# Run the matrix traversal example with a diff&lt;/span&gt;
csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--diff-optimize&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--no-perf&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--report-format&lt;/span&gt; html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--no-perf&lt;/code&gt; flag skips Linux perf counters; we focus on wall‑time and basic metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-O0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;clang++ -O0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Baseline, no optimizations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-O1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;clang++ -O1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Basic optimizations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-O2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;clang++ -O2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Aggressive optimizations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-O3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;clang++ -O3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full optimization, vectorization&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The machine is an AMD Ryzen 7 9700X (8 cores, 16 threads) running Ubuntu&amp;nbsp;24.04.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;p&gt;The only artifact we have in this run is the &lt;code&gt;O0&lt;/code&gt; JSON. It reports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;execution_time_ms:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.142533&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;min:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.129&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;max:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.165&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;mean:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.142533&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;stdev:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.010696&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Artifacts for &lt;code&gt;-O1&lt;/code&gt;, &lt;code&gt;-O2&lt;/code&gt;, and &lt;code&gt;-O3&lt;/code&gt; were not captured in this particular run, so we cannot provide their numbers here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Artifacts missing for this episode — numbers withheld.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;p&gt;Open the generated HTML report. It contains a table with rows for each metric and columns for each optimization level. The &lt;em&gt;diff&lt;/em&gt; column shows the percentage change from &lt;code&gt;-O0&lt;/code&gt;. A negative value means the level is faster; a positive value means slower.&lt;/p&gt;

&lt;p&gt;If you only have the JSON, you can inspect the &lt;code&gt;metrics&lt;/code&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"execution_time_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.142533&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"execution_time_summary_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"min"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.129&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"max"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.165&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.142533&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"median"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.141&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stdev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.010696&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Skipping warm‑up&lt;/strong&gt; – The first run may be slower due to cache misses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring stdev&lt;/strong&gt; – A low mean can hide high variance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assuming &lt;code&gt;-O3&lt;/code&gt; is always best&lt;/strong&gt; – Verify with &lt;code&gt;--diff-optimize&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using the wrong backend&lt;/strong&gt; – Ensure you run on the same device for each level.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Run the same experiment on a different compiler (e.g., GCC 13) and compare the results. Document any differences in the diff report.&lt;/p&gt;

&lt;p&gt;Do this tonight — Episode 14 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;--diff-optimize&lt;/code&gt; flag turns a black‑box claim into a white‑box fact. By looking at the &lt;em&gt;artifact&lt;/em&gt;, you can see exactly where the optimizer helps or hurts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single &lt;code&gt;./a.out&lt;/code&gt; Time Misleads Your Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12: Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;li&gt;Ep 13: Unmasking the O‑3 Myth: Real‑World Optimizer Impact with csperf&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next episode hint
&lt;/h2&gt;

&lt;p&gt;Turning on Linux perf counters with csperf (honestly) — perf counters need honesty&lt;/p&gt;

</description>
      <category>compilers</category>
      <category>optimization</category>
      <category>clang</category>
      <category>csperf</category>
    </item>
    <item>
      <title>Row vs. Column: Measuring Locality with csperf</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Wed, 07 Oct 2026 12:30:08 +0000</pubDate>
      <link>https://dev.to/aabhinavg/row-vs-column-measuring-locality-with-csperf-4563</link>
      <guid>https://dev.to/aabhinavg/row-vs-column-measuring-locality-with-csperf-4563</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;Locality is often taught as a theoretical concept: &lt;em&gt;row‑major&lt;/em&gt; arrays are faster than &lt;em&gt;column‑major&lt;/em&gt; ones because the CPU cache lines are contiguous.  In practice you rarely see a real, reproducible delta.  This episode shows how to turn that intuition into hard evidence with csperf.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ep 1&lt;/strong&gt; – single‑shot timings mislead; use csperf for reproducible evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 2&lt;/strong&gt; – warm‑up and repeat runs are essential.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 3&lt;/strong&gt; – screenshots are not artifacts; csperf gives metadata‑rich evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 4&lt;/strong&gt; – cross‑machine comparison needs machine metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 5&lt;/strong&gt; – csperf observatory commands give quick, reliable evidence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 6&lt;/strong&gt; – csperf doctor diagnoses toolchain issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 7&lt;/strong&gt; – quickstart: 30‑second first win.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 8&lt;/strong&gt; – read csperf JSON, the source of truth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 9&lt;/strong&gt; – choose the right backend for honest measurement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 10&lt;/strong&gt; – stability metrics: min, max, stdev.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ep 11&lt;/strong&gt; – warm‑up deep dive: quantify impact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;People assume that because a program accesses a 2‑D array in row‑major order it will always be faster.  That ignores cache line size, prefetching, and the fact that the compiler can reorder loops or vectorize.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf lets you run the same code with two different access patterns, collect the raw timing and cache‑miss counters, and produce a side‑by‑side diff.  The result is a &lt;em&gt;single&lt;/em&gt; artifact that proves which layout is better on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prepare two small benchmarks&lt;/strong&gt; – one that walks the array row‑by‑row, another that walks column‑by‑column.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run each with the same compiler flags&lt;/strong&gt; (here we use &lt;code&gt;-O3&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collect the JSON artifact&lt;/strong&gt; – it contains execution time, cycles, cache misses, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diff the two JSONs&lt;/strong&gt; – csperf shows the delta in a CSV that you can import into Excel.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Build the row‑major benchmark&lt;/span&gt;
csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/row_major_row_access.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/row.json

&lt;span class="c"&gt;# 2. Build the column‑major benchmark&lt;/span&gt;
csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/row_major_column_access.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/col.json

&lt;span class="c"&gt;# 3. Diff the two artifacts&lt;/span&gt;
csperf diff results/row.json results/col.json &lt;span class="nt"&gt;--csv&lt;/span&gt; results/row-vs-col.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Artifact&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Row JSON&lt;/td&gt;
&lt;td&gt;&lt;code&gt;results/row.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Missing – not captured in the current artifact set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Column JSON&lt;/td&gt;
&lt;td&gt;&lt;code&gt;results/col.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Captured; see below&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diff CSV&lt;/td&gt;
&lt;td&gt;&lt;code&gt;results/row-vs-col.csv&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generated only if both JSONs exist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;p&gt;The column‑major run produced the following key metrics (from &lt;code&gt;results/col.json&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;execution_time_ms&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;10.2044&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;execution_time_summary_ms.mean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10.2044&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;execution_time_summary_ms.min&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10.197&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;execution_time_summary_ms.max&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10.212&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;execution_time_summary_ms.stdev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.006427&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cpu_cycles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;40,883,298&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cache_misses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;327,367&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;l1_cache_misses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3,724,019&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The row‑major artifact is absent, so we cannot compute a numeric delta here.  In a complete run you would see a similar table for the row JSON and then a diff CSV that highlights the difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JSON&lt;/strong&gt; – contains every metric collected; the &lt;code&gt;execution_time_summary_ms&lt;/code&gt; block gives the statistical summary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSV&lt;/strong&gt; – produced by &lt;code&gt;csperf diff&lt;/code&gt;; each row shows a metric and the delta between the two runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XLSX&lt;/strong&gt; – a human‑friendly spreadsheet; open it to see the same numbers in tabular form.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Skipping warm‑up&lt;/strong&gt; – the first run warms the cache and can skew results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different compiler flags&lt;/strong&gt; – ensure both runs use the same &lt;code&gt;-O&lt;/code&gt; level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring stdev&lt;/strong&gt; – a low mean can hide high variance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comparing artifacts from different machines&lt;/strong&gt; – always include machine metadata.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Do this tonight — Episode 13 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;We have turned a textbook claim into a concrete, reproducible measurement.  In the next episode we’ll sweep the optimization level from &lt;code&gt;-O0&lt;/code&gt; to &lt;code&gt;-O3&lt;/code&gt; and see how locality interacts with compiler optimizations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single ./a.out Time Misleads Your Performance Claims &lt;em&gt;(this article)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;li&gt;Ep 12: Row vs. Column: Measuring Locality with csperf&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>performance</category>
      <category>memory</category>
      <category>csperf</category>
    </item>
    <item>
      <title>Warmup Deep Dive: What You’re Throwing Away and Why</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Tue, 06 Oct 2026 12:30:09 +0000</pubDate>
      <link>https://dev.to/aabhinavg/warmup-deep-dive-what-youre-throwing-away-and-why-2mpm</link>
      <guid>https://dev.to/aabhinavg/warmup-deep-dive-what-youre-throwing-away-and-why-2mpm</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;Warm‑up runs are the silent hero of performance measurement.  When you skip them or treat the first run as the final result, you discard the very data that tells you whether your compiler, runtime, or hardware is in a steady state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;p&gt;We have traversed a path of incremental rigor:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: single‑shot timings mislead.&lt;/li&gt;
&lt;li&gt;Ep 2: warm‑up and repeat are essential.&lt;/li&gt;
&lt;li&gt;Ep 3: screenshots are not evidence.&lt;/li&gt;
&lt;li&gt;Ep 4: metadata makes cross‑machine claims reliable.&lt;/li&gt;
&lt;li&gt;Ep 5: csperf observatory gives quick evidence.&lt;/li&gt;
&lt;li&gt;Ep 6: csperf doctor diagnoses toolchain.&lt;/li&gt;
&lt;li&gt;Ep 7: quickstart yields a reproducible artifact in 30 s.&lt;/li&gt;
&lt;li&gt;Ep 8: JSON is the source of truth.&lt;/li&gt;
&lt;li&gt;Ep 9: choosing the right backend.&lt;/li&gt;
&lt;li&gt;Ep 10: stability metrics expose volatility.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Observatory&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have seen how csperf captures machine metadata (Ep 4) and how the doctor command validates the environment (Ep 6).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Measurement&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Today we focus on the &lt;em&gt;warm‑up&lt;/em&gt; phase itself, the first step that often gets ignored.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Comparison&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We will compare two runs: zero warm‑up vs five warm‑up runs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Depth&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The lesson will dig into the numbers that csperf records for each warm‑up iteration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;Many developers assume that the first run of a benchmark is already representative.  In reality, the first few iterations trigger JIT compilation, cache misses, and other transient effects that inflate the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf lets you &lt;strong&gt;explicitly control&lt;/strong&gt; the number of warm‑up runs and then &lt;strong&gt;compare&lt;/strong&gt; the resulting artifacts.  By keeping the repeat count constant, you isolate the effect of warm‑up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;p&gt;Think of a warm‑up run as a &lt;em&gt;pre‑flight check&lt;/em&gt;.  The first few passes prepare the system—load libraries, prime caches, and stabilize the CPU frequency.  The &lt;em&gt;repeat&lt;/em&gt; runs are the actual flight data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install csperf (if not already)&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;csperf

&lt;span class="c"&gt;# Run with no warm‑up&lt;/span&gt;
csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/w0.json

&lt;span class="c"&gt;# Run with five warm‑up runs&lt;/span&gt;
csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/w5.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;p&gt;The machine is an AMD Ryzen 7 9700X, 8 cores, 16 threads, running Ubuntu 24.04.  The csperf artifact &lt;code&gt;csperf/machine.txt&lt;/code&gt; records all relevant metadata.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;p&gt;The zero‑warm‑up run (&lt;code&gt;w0.json&lt;/code&gt;) produced:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;execution_time_ms&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5.1514&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;min&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5.135&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5.176&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5.1514&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;median&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5.145&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stdev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.017897&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cpu_cycles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;6 125 891&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ref_cycles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4 346 136&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;frontend_stall_cycles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1 241 045&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;instruction_count&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12 224 343&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;branch_instructions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1 707 665&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;branch_mispredictions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;13 665&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cache_references&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;588 738&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cache_misses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;85 287&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;l1_cache_misses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;235 771&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;l1_icache_misses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;30 324&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dtlb_load_misses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4 684&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;itlb_load_misses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;260&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;amd_l2_ic_dc_miss_in_l2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;103 151&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ipc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.995521&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;l2_cache_misses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;103 151&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The five‑warm‑up run (&lt;code&gt;w5.json&lt;/code&gt;) is pending; we will generate it tomorrow.  Until then, the numbers above illustrate the &lt;em&gt;baseline&lt;/em&gt; you would see if you ignored warm‑up.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;metrics.execution_time_ms&lt;/code&gt;&lt;/strong&gt; is the aggregate time over the repeat runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;metrics.execution_time_summary_ms&lt;/code&gt;&lt;/strong&gt; gives the statistical spread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;metrics.cpu_cycles&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;metrics.ref_cycles&lt;/code&gt;&lt;/strong&gt; show the raw instruction throughput.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;metrics.frontend_stall_cycles&lt;/code&gt;&lt;/strong&gt; reveals how often the CPU stalled waiting for the compiler front‑end.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;metrics.cache_*&lt;/code&gt;&lt;/strong&gt; metrics expose the cost of memory traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you later run &lt;code&gt;w5.json&lt;/code&gt;, compare each of these fields to see how many cycles and how much time the warm‑up phase saved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Skipping warm‑up&lt;/strong&gt; – leads to inflated times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using the first run as the final result&lt;/strong&gt; – ignores transient effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not keeping repeat count constant&lt;/strong&gt; – conflates warm‑up and repeat variability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring the &lt;code&gt;execution_time_summary_ms&lt;/code&gt;&lt;/strong&gt; – hides the spread.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overlooking cache metrics&lt;/strong&gt; – misses a major source of variance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Run the five‑warm‑up experiment on your machine.  Compare the &lt;code&gt;execution_time_ms&lt;/code&gt; and &lt;code&gt;cpu_cycles&lt;/code&gt; between &lt;code&gt;w0.json&lt;/code&gt; and &lt;code&gt;w5.json&lt;/code&gt;.  Note how the warm‑up reduces the mean time and the standard deviation.&lt;/p&gt;

&lt;p&gt;Do this tonight — Episode 12 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Warm‑up is not a luxury; it is the first honest measurement step.  By controlling and comparing it, you turn a noisy signal into a reliable metric.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single ./a.out Time Misleads Your Performance Claims &lt;em&gt;(this article)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;li&gt;Ep 11: Warmup Deep Dive: What You’re Throwing Away and Why&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Teaser next
&lt;/h2&gt;

&lt;p&gt;Recall how we used metadata to compare machines (Ep 4) and now we’ll dive into locality: Row vs column access and how layout shows up in time (Ep 12).&lt;/p&gt;

</description>
      <category>benchmarking</category>
      <category>csperf</category>
      <category>performance</category>
      <category>methodology</category>
    </item>
    <item>
      <title>Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens</title>
      <dc:creator>compilersutra</dc:creator>
      <pubDate>Mon, 05 Oct 2026 12:30:07 +0000</pubDate>
      <link>https://dev.to/aabhinavg/stability-metrics-min-max-and-standard-deviation-as-first-class-citizens-3alo</link>
      <guid>https://dev.to/aabhinavg/stability-metrics-min-max-and-standard-deviation-as-first-class-citizens-3alo</guid>
      <description>&lt;h2&gt;
  
  
  Why this lesson exists
&lt;/h2&gt;

&lt;p&gt;When you look at a single mean you miss the story of variability.  A program that sometimes runs in 5 ms and sometimes in 10 ms can still have a mean of 7.5 ms – a perfectly plausible number that hides a performance cliff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap — where we are in the series
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Ep 1: &lt;em&gt;Why a Single ./a.out Time Misleads Your Performance Claims&lt;/em&gt; – single‑shot timings are unreliable.&lt;/li&gt;
&lt;li&gt;Ep 2: &lt;em&gt;Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/em&gt; – warm‑up and repeat runs give reproducible data.&lt;/li&gt;
&lt;li&gt;Ep 3: &lt;em&gt;Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/em&gt; – artifacts beat screenshots.&lt;/li&gt;
&lt;li&gt;Ep 4: &lt;em&gt;Comparing Across Machines: Why Metadata Matters in csperf&lt;/em&gt; – metadata enables honest cross‑machine comparison.&lt;/li&gt;
&lt;li&gt;Ep 5: &lt;em&gt;csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/em&gt; – observatory commands give quick evidence.&lt;/li&gt;
&lt;li&gt;Ep 6: &lt;em&gt;csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/em&gt; – validate toolchain before blaming performance.&lt;/li&gt;
&lt;li&gt;Ep 7: &lt;em&gt;csperf Quickstart: 30‑Second First Win&lt;/em&gt; – first reproducible artifact in half a minute.&lt;/li&gt;
&lt;li&gt;Ep 8: &lt;em&gt;Reading csperf JSON: The Real Performance Artifact&lt;/em&gt; – JSON is the source of truth.&lt;/li&gt;
&lt;li&gt;Ep 9: &lt;em&gt;Backends 101: Choosing the Right Measurement Surface&lt;/em&gt; – list backends, enumerate devices, run workloads on the correct surface.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The misconception
&lt;/h2&gt;

&lt;p&gt;People often report only the mean execution time.  They ignore that the mean can be the same for wildly different distributions – a narrow bell curve or a long tail.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem csperf solves (this episode's slice)
&lt;/h2&gt;

&lt;p&gt;csperf now exposes &lt;strong&gt;min, max, and standard deviation&lt;/strong&gt; in the summary block, making volatility visible.  You can spot outliers, decide whether to discard them, and compare stability across compiler flags.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental model
&lt;/h2&gt;

&lt;p&gt;Think of a performance run as a &lt;em&gt;distribution&lt;/em&gt; of samples.  The mean tells you the center, but the min/max and stdev tell you the spread.  A low stdev means you can trust the mean; a high stdev means you should look deeper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: install and first commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install csperf if you haven’t already&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;csperf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lab: what we ran on this machine
&lt;/h2&gt;

&lt;p&gt;We used the matrix traversal example on an AMD Ryzen 7 9700X.  The command sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;csperf run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; examples/cpp/matrix_traversal.cpp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--backend&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--warmup-runs&lt;/span&gt; 3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repeat-runs&lt;/span&gt; 10 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; results/stable.json
csperf profile results/stable.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Results (real numbers only)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_ms&lt;/td&gt;
&lt;td&gt;5.1458&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_summary_ms.min&lt;/td&gt;
&lt;td&gt;5.132&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_summary_ms.max&lt;/td&gt;
&lt;td&gt;5.162&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_summary_ms.mean&lt;/td&gt;
&lt;td&gt;5.1458&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;execution_time_summary_ms.stdev&lt;/td&gt;
&lt;td&gt;0.010358&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cpu_cycles&lt;/td&gt;
&lt;td&gt;7 317 425&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ipc&lt;/td&gt;
&lt;td&gt;1.68653&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to read the artifacts
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;results/stable.json&lt;/code&gt;.  The &lt;code&gt;execution_time_summary_ms&lt;/code&gt; object contains &lt;code&gt;count&lt;/code&gt;, &lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;mean&lt;/code&gt;, &lt;code&gt;median&lt;/code&gt;, and &lt;code&gt;stdev&lt;/code&gt;.  The &lt;code&gt;metrics&lt;/code&gt; section shows raw counters.  The &lt;code&gt;artifacts&lt;/code&gt; field lists CSV/XLSX for spreadsheet analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes (teacher checklist)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring stdev&lt;/strong&gt; – assume mean is enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using too few repeats&lt;/strong&gt; – 10 runs is a minimum for stable stats.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discarding warm‑ups&lt;/strong&gt; – warm‑up runs are intentional discards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comparing across machines without metadata&lt;/strong&gt; – always check the &lt;code&gt;hardware&lt;/code&gt; section.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try this next (homework)
&lt;/h2&gt;

&lt;p&gt;Run the same workload with &lt;code&gt;--repeat-runs 20&lt;/code&gt; and compare the stdev.  Does it shrink?  Document the change.&lt;/p&gt;

&lt;p&gt;Do this tonight — Episode 11 starts by assuming you did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Stability metrics let you see whether a mean is trustworthy.  In the next episode we’ll dig into what warm‑up runs actually discard and why that matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The series so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ep 1: Why a Single ./a.out Time Misleads Your Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 2: Warm vs Cold: Why a Single Trial Misleads Performance Claims&lt;/li&gt;
&lt;li&gt;Ep 3: Screenshots Aren't Evidence: Use csperf for Real Performance Artifacts&lt;/li&gt;
&lt;li&gt;Ep 4: Comparing Across Machines: Why Metadata Matters in csperf&lt;/li&gt;
&lt;li&gt;Ep 5: csperf: A Lightweight Observatory for Honest Performance Tracking&lt;/li&gt;
&lt;li&gt;Ep 6: csperf Doctor: First Command to Diagnose Toolchain Issues&lt;/li&gt;
&lt;li&gt;Ep 7: csperf Quickstart: 30‑Second First Win&lt;/li&gt;
&lt;li&gt;Ep 8: Reading csperf JSON: The Real Performance Artifact&lt;/li&gt;
&lt;li&gt;Ep 9: Backends 101: Choosing the Right Measurement Surface&lt;/li&gt;
&lt;li&gt;Ep 10: Stability Metrics: Min, Max, and Standard Deviation as First-Class Citizens&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>benchmarking</category>
      <category>statistics</category>
      <category>csperf</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
