# Share a JMH Benchmark Report — With the Error Bars Still Attached

Canonical: https://commareports.com/share-jmh-benchmark-report
Published: 2026-09-08

> JMH prints a score and a ± that everyone drops when they quote it. Render the JSON with jmh-visualizer and publish to Comma for a URL where the confidence interval survives.

# Share a JMH benchmark report

JMH is careful in a way that gets discarded the moment results are shared. It
runs warmup iterations, forks JVMs to defeat profile pollution, and reports a
score *with* an error bound:

```
Benchmark                Mode  Cnt   Score   Error  Units
SerdeBench.jackson      thrpt   15  482.113 ± 9.244  ops/ms
SerdeBench.handRolled   thrpt   15  501.882 ± 22.71  ops/ms
```

And then somebody writes "hand-rolled is 4% faster" in a pull request. Look at
the error bars: the intervals overlap. The benchmark does not say that.

Sharing the rendered artifact rather than a remembered number is most of the
fix.

## Get JSON, then render it

```bash
# from the benchmarks jar
java -jar target/benchmarks.jar -rf json -rff result.json

# or via the Gradle/Maven plugin, then render
npx jmh-visualizer result.json -o report/
```

jmh-visualizer writes a static folder — the chart bundle plus your data — with
the score, the error bars, the per-fork breakdown and the secondary metrics
(`-prof gc` allocation rates, if you collected them).

## Publish the folder

Drag `report/` (or a zip of it) into [the app](https://commareports.com/):

- `index.html` becomes the **report body**.
- The chart JS and your result JSON upload alongside it, with relative
  references rewritten to the uploaded copies.
- Scripts run inside a sandboxed iframe (`allow-scripts`, no
  `allow-same-origin`), so the charts render and the per-benchmark drilldown
  works.

Or send the entry file to the API:

```bash
curl -fsS -X POST "https://commareports.com/api/v1/reports" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html report/index.html \
        --arg t "JMH — serialization, JDK 21" '{title: $t, html: $html}')"
```

## Collect the profilers while you are there

A score tells you *that* something changed. The profilers tell you why, and they
cost one flag:

```bash
java -jar target/benchmarks.jar -rf json -rff result.json \
  -prof gc \
  -prof perfasm    # Linux, needs perf
```

`-prof gc` in particular turns "faster" into "allocates 40% less per op", which
is the version of the claim that survives review.

## From CI, carefully

Shared CI runners share CPU, so absolute JMH numbers from CI are not
publication-grade. They are still useful as a regression tripwire with a
generous threshold. PATCH one report id per suite:

```bash
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html report/index.html \
        --arg t "JMH — serialization @ $GITHUB_SHA" '{title: $t, html: $html}')"
```

The revision list then shows the run-to-run spread, which is the honest way to
decide whether a 6% drop is a regression or the runner.

## What review adds

- **Anchored threads** on the benchmark under debate — see
  [commenting on HTML](/comment-on-html).
- **Revisions**, so the noise floor is visible rather than assumed.
- **Access per report** — private, team, domain-gated or named reviewers. See
  the [sharing model](/docs/sharing).

## Limits

- **Entry HTML: 5 MB.** Assets: 25 MB per file, 250 MB and 500 files total. A
  large parameterized sweep is the JSON to watch.
- **60 requests/minute per token.**

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision
history.

**[Publish a benchmark →](https://commareports.com/)**

### Related

- [Share a Criterion benchmark report](/share-criterion-benchmark-report) · [Share a benchmark report](/share-benchmark-report)
- [Share an async-profiler report](/share-async-profiler-report) · [Share a Gradle test report](/share-gradle-test-report)
- [Share a JaCoCo report](/share-jacoco-report) · [Publish from CI](/docs/ci)
