What Output Formats Does nanobench Support?

Updated

nanobench supports four built-in output formats—CSV, JSON, HTML box plots, and Python's pyperf format—plus custom rendering through Mustache-like templates. You get these by calling render() on a benchmark result or comparison result and passing a template from the ankerl::nanobench::templates namespace. The default console output is a table whose columns you can control; the template formats are for feeding results into other tools or reports.

Default table output and column control

When you run a benchmark without rendering a template, nanobench prints a table. The documentation lists these columns: relative, complexityN, timePerUnit, unitPerSecond, error, instructions, cycles, ipc, branches, branchMisses, total, and _size.

You can shape this table with hideColumn(), showColumn(), and isColumnVisible(). Context values can also be promoted into their own columns via contextColumn() and clearContextColumns(), which is useful when you sweep a parameter and want each value visible per row.

Built-in templates

All built-in templates live in ankerl::nanobench::templates and are passed to render():

Template Function Typical use
CSV templates::csv / csv() Spreadsheet import, diffing runs
JSON templates::json / json() Storing results, downstream tooling
HTML box plot templates::htmlBoxplot / htmlBoxplot() Visualizing run-to-run spread
pyperf templates::pyperf / pyperf() Consuming results with Python's pyperf module

The documentation also covers CSV specifically for comparisons ("CSV for a comparison") and a section on how precise a comparison is, so if you plan to compare alternatives, read those before trusting small differences.

Rendering a result

The pattern is: run the benchmark, keep the Result, then render it with a template. Conceptually:

ankerl::nanobench::Bench b;
b.title("example").unit("op");
b.run("something fast", [&] { /* work */ });

// Render the most recent result
ankerl::nanobench::render(ankerl::nanobench::templates::json(), b.results());

Bench::results() returns the collected Result objects, and render() accepts a template plus results. For comparisons, CompareResult has its own render() overload, so you render the comparison outcome rather than individual results.

Custom Mustache-like templates

Beyond the built-ins, render() accepts Mustache-like templates, so you can produce any text format—Markdown tables, custom logs, config fragments—by writing a template with placeholders. The documentation's "Rendering" and "Mustache-like Templates" sections describe the syntax, and "Time Units in Templates" explains how time values are formatted inside templates. If you need a unit other than the default in your output, set it with timeUnit() on the bench or handle it in the template.

Practical notes

  • Comparisons need the comparison path. Use compare() and render the resulting CompareResult; isSignificant() and fastest() tell you whether a difference is meaningful before you publish it.
  • CSV and JSON are the safe interchange formats. If another tool will read the output, prefer these over scraping the console table.
  • Box plots need multiple rounds. The HTML box plot template is only informative when the benchmark ran enough epochs to show spread; check epochs() and related settings if the plot looks degenerate.
  • pyperf output targets Python tooling. Use it when your analysis pipeline already uses the pyperf module; otherwise JSON is more general.

For exact template names, placeholder syntax, and the comparison-specific CSV behavior, consult the corresponding sections of the nanobench documentation, since the API reference lists each template function individually.