Go Benchmark Comparison and the hard part of small deltas
Go benchmark deltas are easy to overstate. This tool compares two `go test -bench` outputs with a Mann-Whitney U test, median change, and a plain answer when the sample is too thin to support a call.
Small performance changes are where teams lose time. A benchmark moves by a few percent, someone posts a chart, and the room starts arguing. Was the code faster. Was the machine noisy. Was the sample too small. Most benchmark writeups skip the part that matters, which is whether your evidence supports the claim.
Go Benchmark Comparison — is that 4% real? exists for this exact problem. You paste two go test -bench outputs and get a comparison built around the Mann-Whitney U test, plus median change and a plain answer when the data does not support a call. The useful part is not the percentage alone. It is the discipline of separating observed difference from evidence of a stable difference.
If you work on Go services, this matters in code review, release validation, and regression triage. Small benchmark deltas often sit near the noise floor. CPU frequency scaling, allocator state, background load, and benchmark setup all distort results. A tool in this class is valuable when it resists overclaiming and tells you when the experiment was weak.
Inspect the shape of the input first
go test -bench output looks simple, but the quality of the conclusion depends on what you feed it. Before you compare two runs, inspect the benchmark design.
Start with repetition. A single before-and-after line is weak evidence. Statistical comparison needs multiple observations in each group. If your benchmark output includes one sample per case, the comparison has little room to distinguish signal from noise. The right answer in many of those cases is uncertainty, not a winner.
Then inspect benchmark stability. You want the same benchmark name, same code path, same environment, and the same measurement unit across both pasted outputs. If one side reports ns/op and the other side reflects a different benchmark target or setup, the comparison becomes invalid even if the names look close.
Also inspect scope. Go benchmarks often report more than time, such as B/op and allocs/op. Those metrics answer different questions. A runtime change with flat allocations means something different from an allocation drop with flat runtime. A good comparison flow keeps each metric separate instead of collapsing them into one verdict.
This is where many systems go wrong. They accept benchmark text as if every line were comparable. In practice, benchmark data is semi-structured text with hidden assumptions. The parser needs to match cases correctly, keep units distinct, and avoid presenting mismatched rows as evidence.
Why median and Mann-Whitney U are a sound default
Benchmark data is messy. It often has outliers. One interrupted run, one scheduler hiccup, one thermal event, and the mean shifts more than the code changed. Median is a practical summary because it is less sensitive to those spikes.
The same logic applies to the test choice. The Mann-Whitney U test compares two groups without assuming a normal distribution. For benchmark outputs, that is a sane default. You often do not know the underlying distribution, and pretending otherwise gives false precision.
What this demonstrates is a design choice many engineering tools should copy. Match the method to the shape of the data, not to convention. If your samples are small, skewed, or noisy, robust summaries and non-parametric tests usually tell a more honest story than a polished average.
You should still read the result correctly. A p-value is not effect size. It does not tell you whether a change matters to your users or your system. It tells you how compatible the observed difference is with the idea that the two sets came from the same distribution. That is why the median change belongs beside it. One metric describes magnitude. The other describes strength of evidence.
Systems in this class commonly fail in two ways. They either show percent change without uncertainty, or they show a significance value without practical magnitude. Both are incomplete. Engineers need both pieces to reason about a performance claim.
How to verify what the result is telling you
A benchmark comparison should be easy to challenge. You should be able to look at the raw pasted outputs and ask whether the conclusion follows.
First, count observations. If one or both sides have too few repeated measurements, treat any apparent win with caution. The tool’s value is highest when it says there is not enough data to tell. That answer protects you from turning random variation into roadmap work.
Second, check whether the direction and the distribution agree. If the median improved by a small amount, but the individual samples overlap heavily, the statistical test should reflect that uncertainty. If it does not, inspect the input for parsing issues or hidden mismatches.
Third, verify benchmark comparability. The benchmark names must line up. The metric units must line up. The execution context should be close enough for the samples to mean the same thing. A result built from non-comparable cases is cleanly formatted noise.
Fourth, rerun the experiment. If a claimed improvement persists across fresh runs under controlled conditions, confidence grows. If it disappears, you learned something useful about environmental sensitivity. The tool does not replace experiment design. It makes weak design harder to ignore.
For practical use, it helps to treat the output as one step in a loop:
- run enough benchmark repetitions
- compare before and after
- inspect median change and p-value together
- rerun under tighter controls if the claim is important
- decide based on both evidence strength and engineering impact
That loop is simple, but it is stricter than the way performance claims often spread through a team.
Where benchmark comparison tools often go wrong
The biggest failure mode is false certainty. A tool accepts thin data and returns a crisp ranking. Users see a percentage and stop thinking. That is how tiny regressions get escalated and tiny improvements get celebrated long before they are real.
Another failure mode is hidden preprocessing. If a system drops unmatched rows, merges metrics, or normalizes units in a way the user cannot inspect, it becomes hard to audit. Benchmark comparison should stay close to the raw text so you can trace each reported result back to a specific benchmark line.
A third problem is overfitting to one summary statistic. Means are common because they are familiar. They are also easy to distort with outliers. Median avoids some of that, but no single statistic tells the whole story. The design lesson here is modesty. Summarize the data, test the difference, and leave room for uncertainty.
There is also a user-interface issue. Performance tools often bury the assumptions. A better design puts them in the open. If the method is Mann-Whitney U, say so. If the answer is inconclusive because the data is thin, say so plainly. Engineers make better decisions when the tool exposes the limits of the evidence.
What this demonstrates about engineering judgment
This tool is about more than Go benchmarks. It shows what responsible analysis looks like in everyday engineering. You take noisy operational data, choose a method that fits the data, and refuse to claim more than the evidence supports.
That stance matters because performance work attracts narrative bias. A patch was hard to write, so people expect a gain. A refactor looked risky, so people expect a loss. Statistical comparison is useful because it pushes back on those expectations. It gives your team a shared way to ask whether the observed change is likely to be real.
It also encourages better benchmark hygiene. Once you know thin samples lead to honest uncertainty, you are more likely to collect enough runs, isolate the environment, and keep benchmark cases comparable. The output shape influences the experiment shape.
What to watch next
When you use a benchmark comparison tool, watch for three things. More repeated samples. Cleaner benchmark isolation. Clear separation between effect size and evidence strength. Those are the signals that turn a percentage change into a result you can defend.
If a 4 percent shift disappears when you rerun with tighter controls, the lesson is still useful. Your benchmark was measuring more than your code. If it persists across repeated runs and the comparison stays consistent, you have a stronger case for action. Either way, the honest answer starts with the data you collected, not the story you hoped to tell.