Generate markdown comparison tables from `cargo-criterion` JSON output

Overview

criterion-table

Crate Docs

Generate markdown comparison tables from Cargo Criterion benchmark JSON output.

Currently, the tool is limited to Github Flavored Markdown (GFM), but adding new output types is relatively simple.

Generated Markdown Examples

Very Basic Report

FlexStr Benchmark Report

Installation

# If you don't have it already
cargo install cargo-criterion

# This project
cargo install criterion-table

Usage

  1. Ensure your benchmarks meet these basic criteria:
  • Benchmark IDs are formatted in two to three sections separated by forward slashes (/)
    • The sections are used like this: / /[row_name]
    • Case is not currently altered, so set appropriately for display
    • Row name is the only optional field, and if left blank, all results will be a single blank row
    • If using a very basic benchmark_function you would only get a column name by default, which isn't sufficient
    • If using benchmark groups you will get two sections automatically
    • If using benchmark groups and BenchmarkId you will get all three sections automatically
  • Benchmark data is not reordered, so ensure they execute in the order desired
    • Tables are ordered based on the order they are seen in the data (execution order)
    • The first column seen in each row will be the baseline everything else in that row is compared to, so benchmark execution order matters

Benchmark Example 1 - Manual ID

use criterion::{black_box, criterion_group, criterion_main, Criterion};

#[inline]
fn fibonacci(n: u64) -> u64 {
  match n {
    0 => 1,
    1 => 1,
    n => fibonacci(n-1) + fibonacci(n-2),
  }
}

pub fn criterion_benchmark(c: &mut Criterion) {
    let id = "Fibonacci/Recursive Fib/20";
    c.bench_function(id, |b| b.iter(|| fibonacci(black_box(20))));
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

Benchmark Example 2 - Benchmark Group with Parameters

use criterion::{black_box, BenchmarkId, criterion_group, criterion_main, 
                Criterion};

#[inline]
fn fibonacci(n: u64) -> u64 {
  match n {
    0 => 1,
    1 => 1,
    n => fibonacci(n-1) + fibonacci(n-2),
  }
}

pub fn criterion_benchmark(c: &mut Criterion) {
    let mut group = c.benchmark_group("Fibonacci");
    
    for row in vec![10, 20] {
        let id = BenchmarkId::new("Recursive Fib", row);
        group.bench_with_input(id, &row, |b, row| {
            b.iter(|| fibonacci(black_box(*row)))
        });
    }
    
    group.finish();
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
  1. Create a tables.toml configuration file (Optional)

This allows you to add commentary to integrate with the tables in the markdown. Table names are in lowercase and spaces replaced with dashes. The file must be in the local directory. Here is an example:

[top_comments]
Overview = """
This is a benchmark comparison report.
"""

[table_comments]
fibonacci = """
Since `fibonacci` is not tail recursive or iterative, all these function calls 
are not inlined which makes this version very slow.
"""
  1. Run Benchmarks and Generate Markdown

This can be done in a couple of different ways:

Single Step

This method ensures all benchmarks are included in one step

# Run all benchmarks and convert into the markdown all in one step
cargo criterion --message-format=json | criterion-table > BENCHMARKS.md

Multiple Steps

This method allows better control of order and which benchmarks are included

# Execute only the desired benchmarks
cargo criterion --bench recursive_fib --message-format=json > recursive_fib.json
cargo criterion --bench iterative_fib --message-format=json > iterative_fib.json

# Reorder before converting into markdown
cat iterative_fib.json recursive_fib.json | criterion-table > BENCHMARKS.md

Adding New Output File Types

Currently, the tool is hardcoded to GFM, but it is easy to add a new output type via the Formatter trait by creating your own new binary project

  1. Add this crate, FlexStr, and IndexMap to your binary project
[dependencies]
criterion-table = "0.4"
flexstr = "0.8"
indexmap = "1"
  1. Create a new type and implement Formatter

  2. Create a main function and call build_tables

NOTE: Replace GFMFormatter with your new formatter below

{ println!("{data}"); } Err(err) => { eprintln!("An error occurred processing Criterion data: {err}"); } } }">
use std::io;

use criterion_table::build_tables;
// Replace with your formatter
use criterion_table::formatter::GFMFormatter;

const TABLES_CONFIG: &str = "tables.toml";

fn main() {
    // Replace `GFMFormatter` with your formatter
    match build_tables(io::stdin(), GFMFormatter, TABLES_CONFIG) {
        Ok(data) => {
            println!("{data}");
        }
        Err(err) => {
            eprintln!("An error occurred processing Criterion data: {err}");
        }
    }
}
  1. Save the returned String to the file type of your formatter or write to stdout

License

This project is licensed optionally under either:

You might also like...
Rust implementation of PRECIS Framework: Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols

Rust PRECIS Framework libray PRECIS Framework: Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols as descr

Clearly a repo about websockets and their comparison...

Tags Go vs Typescript: Video 1 of the series is tag go-vs-ts-video-1 Current Project Video 2 and 3 are going to be likely Go vs Rust vs Typescript, bu

rust channel benchmarks to keep stat of performance of Kanal library in comparison with other competitors.
rust channel benchmarks to keep stat of performance of Kanal library in comparison with other competitors.

Rust Channel Benchmarks This is a highly modified fork of the crossbeam-channel benchmarks. to keep track of Kanal library stats in comparison with ot

A collection of comparison-benchmarks for Nova & related Proving systems

Nova benchmarks Here's a list of some of the benchmarks we've been taking to better understand how Nova performs vs other proof systems. Live version:

A cargo subcommand that displays ghidra function output through the use of the rizin rz-ghidra project.

cargo-rz-ghidra A cargo subcommand that displays ghidra function output through the use of the rizin rz-ghidra project. Install cargo install --git ht

Convenience wrapper for cargo buildscript input/output

A convenience wrapper for cargo buildscript input/output. Why? The cargo buildscript API is (necessarily) stringly-typed.

Formats output of Solana's cargo test-bpf/test-sbf command
Formats output of Solana's cargo test-bpf/test-sbf command

solfmt Formats output of Solana's cargo test-bpf/test-sbf command. Installation cargo install solfmt Usage Run the your test command as usual (cargo t

A Rust command that prettifies the ugly `cargo test` output into a beautiful one.
A Rust command that prettifies the ugly `cargo test` output into a beautiful one.

Cargo Pretty Test โœจ A Rust command-line tool that prettifies the ugly cargo test output into a beautiful output. This crate can be also used as a libr

Get JSON values quickly - JSON parser for Rust
Get JSON values quickly - JSON parser for Rust

get json values quickly GJSON is a Rust crate that provides a fast and simple way to get values from a json document. It has features such as one line

Schema2000 is a tool that parses exsiting JSON documents and tries to derive a JSON schema from these documents.

Schema 2000 Schema2000 is a tool that parses exsiting JSON documents and tries to derive a JSON schema from these documents. Currently, Schema2000 is

:large_orange_diamond: Build beautiful terminal tables with automatic content wrapping
:large_orange_diamond: Build beautiful terminal tables with automatic content wrapping

Comfy-table Comfy-table tries to provide utility for building beautiful tables, while being easy to use. Features: Dynamic arrangement of content to a

A Rust library to manipulate AArch64 VMSA EL1 page tables.

aarch64 page table manipulation This crate provides a library to manipulate EL1 page tables conforming to the AArch64 Virtual Memory System Architectu

Command-line tool to make Rust source code entities from Postgres tables.

pg2rs Command-line tool to make Rust source code entities from Postgres tables. Generates: enums structs which can be then used like mod structs; use

An easy to use library for pretty print tables of Rust structs and enums.
An easy to use library for pretty print tables of Rust structs and enums.

tabled An easy to use library for pretty printing tables of Rust structs and enums. Table of Contents Usage Settings Style Themes ASCII Psql Github Ma

XLite - query Excel (.xlsx, .xls) and Open Document spreadsheets (.ods) as SQLite virtual tables

XLite - query Excel (.xlsx, .xls) and Open Document spreadsheets (.ods) as SQLite virtual tables XLite is a SQLite extension written in Rust. The main

Convert rust coverage data to HTML reports, LCOV files or terminal tables

Coverage Prepare Convert coverage data to HTML reports, LCOV files or terminal tables. coverage-prepare --help: Convert "profraw" coverage data to: *

A library for parsing and generating ESP-IDF partition tables

esp-idf-part A library for parsing and generating ESP-IDF partition tables. Supports parsing from and generating to both CSV and binary formats. This

A simple CLI for creating and managing Solana Lookup Tables.

LUT - A simple CLI for creating and managing Solana Lookup Tables Commands lut create Creates a new LUT using the default keypair in the Solana config

PostQuet: Stream PostgreSQL tables/queries to Parquet files seamlessly with this high-performance, Rust-based command-line tool.

STATUS: IN DEVELOPMENT PostQuet: Streaming PostgreSQL to Parquet Exporter PostQuet is a powerful and efficient command-line tool written in Rust that

Owner
Scott Meeuwsen
Scott Meeuwsen
cargo-generate template for Criterion benchmarks

Criterion Benchmark Template This is a cargo-generate template for quickly creating benchmarks using the Criterion benchmarking framework. Usage $ car

Lily Mara 4 Jan 19, 2023
Converts cargo check (and clippy) JSON output to the GitHub Action error format

cargo-action-fmt Takes JSON-formatted cargo check (and cargo clippy) output and formats it for GitHub actions. Examples This tool can be used with a v

Oliver Gould 8 Oct 12, 2022
A cargo plugin to shrink cargo's output

cargo single-line A simple cargo plugin that shrinks the visible cargo output to a single line (okay, in the best case scenario). In principle, the pl

Denis 5 Oct 30, 2022
An AWS Lambda for automatically loading JSON files as they're created into Delta tables

Delta S3 Loader This AWS Lambda serves a singular purpose: bring JSON files from an S3 bucket into Delta Lake. This can be highly useful for legacy or

R. Tyler Croy 4 Jan 12, 2022
Cargo-about - ๐Ÿ“œ Cargo plugin to generate list of all licenses for a crate ๐Ÿฆ€

?? cargo-about Cargo plugin for generating a license listing for all dependencies of a crate See the book ?? for in-depth documentation. Please Note:

Embark 281 Jan 1, 2023
A Faster(โšก) formatter, linter, bundler, and more for JavaScript, TypeScript, JSON, HTML, Markdown, and CSS Lapce Plugin

Lapce Plugin for Rome Lapce-rome is a Lapce plugin for rome, The Rome is faster โšก , A formatter, linter, compiler, bundler, and more for JavaScript, T

xiaoxin 7 Dec 16, 2022
Generate markdown footer links.

WIP Generate markdown footer links.

Arijit Basu 8 Nov 20, 2022
A comparison of operating systems written in Rust

Rust OS comparison A comparison of operating systems written in Rust. There are several open source operating systems written in Rust. Most of them ar

Markus Kohlhase 492 Jan 8, 2023
Simple comparison app for iRacing car setups.

CarTunes Simple comparison app for iRacing car setups. About Export a setup in the iRacing garage and CarTunes will let you compare it with other setu

Jay Oster 31 Jan 7, 2023
๐Ÿงน Quick & dirty fuzzy path comparison

?? fuzzypath Quick & dirty fuzzy path comparison Comparison rules โœ… Case insensitive โœ… Backslashes are normalized to forward slashes โœ… Trailing slashe

William 4 May 19, 2022