#runner #formatting

dev brunch

A simple micro-benchmark runner

10 releases

Uses new Rust 2021

0.2.6 Jun 18, 2022
0.2.4 Mar 20, 2022
0.2.1 Dec 2, 2021
0.2.0 Oct 21, 2021
0.1.2 Mar 2, 2021

#20 in Profiling

Download history 86/week @ 2022-03-16 73/week @ 2022-03-23 48/week @ 2022-03-30 42/week @ 2022-04-06 90/week @ 2022-04-13 26/week @ 2022-04-20 65/week @ 2022-04-27 81/week @ 2022-05-04 213/week @ 2022-05-11 263/week @ 2022-05-18 129/week @ 2022-05-25 93/week @ 2022-06-01 100/week @ 2022-06-08 69/week @ 2022-06-15 67/week @ 2022-06-22 66/week @ 2022-06-29

302 downloads per month
Used in fewer than 9 crates

WTFPL license

27KB
458 lines

Brunch

Documentation crates.io Build Status Dependency Status

Brunch is a very simple Rust micro-benchmark runner inspired by easybench. It has roughly a million times fewer dependencies than criterion, does not require nightly, and maintains a "last run" state so can show relative changes benchmark-to-benchmark. The formatting is also quite pretty.

As with all Rust benchmarking, there are a lot of caveats, and results might be artificially fast or slow. For best resuilts, build optimized, avoid heavy setup contexts, and test different bench setups to find the most "honest" representation.

In theory, this library can reach pico-second scales (it clocks increasingly large batches and divides accordingly), but background noise and setup overhead will likely prevent times getting quite as low as they might "actually" be. It can go as long as milliseconds, but might require increased time limits to reach sufficient samples in such cases.

Work in Progress

This crate is still under heavy development. It is subject to going to change, so you probably don't want to rely on it in production yet. But that said, feel free to poke around, steal code, find inspiration, etc.

Installation

Add brunch to your dev-dependencies in Cargo.toml, like:

[dev-dependencies]
brunch = "0.2.*"

Benchemarks are also defined in Cargo.toml the usual way. Just be sure to set harness = false:

[[bench]]
name = "encode"
harness = false

Usage

Setup is currently simple if primitive, requiring you drop a call to brunch::benches!() in the benchmark file. It will generate a main() method, run the supplied benchmarks, and give you the results.

An example bench file would look something like:

use brunch::Bench;
use dactyl::NiceU8;
use std::time::Duration;

brunch::benches!(
    Bench::new("dactyl::NiceU8", "from(0)")
        .timed(Duration::from_secs(1))
        .with(|| NiceU8::from(0_u8)),

    Bench::new("dactyl::NiceU8", "from(18)")
        .timed(Duration::from_secs(1))
        .with(|| NiceU8::from(18_u8)),

    Bench::new("dactyl::NiceU8", "from(101)")
        .timed(Duration::from_secs(1))
        .with(|| NiceU8::from(101_u8)),

    Bench::new("dactyl::NiceU8", "from(u8::MAX)")
        .timed(Duration::from_secs(1))
        .with(|| NiceU8::from(u8::MAX))
);

The Bench struct represents a benchmark. It takes two label arguments intended to represent a shared base (for the included benchmarks) and the unique bit, usually a method/value.

By default, each benchmark will run for approximately three seconds. This can be changed using the chained Bench::timed method as shown above.

There are currently three styles of callback:

Method Signature Description
with FnMut() -> O Execute a self-contained callback.
with_setup FnMut(I) -> O Execute a callback seeded with a (cloneable) value.
with_setup_ref FnMut(&I) -> O Execute a callback seeded with a referenced value.

The benchmarks are run in the order entered, and their results likewise follow that same ordering.

If you want to break up the results visually, you can add a call to Bench::spacer anywhere you want a break to occur, like:

brunch::benches!(
    Bench::new("dactyl::NiceU8", "from(0)")
        .with(|| NiceU8::from(0_u8)),

    Bench::new("dactyl::NiceU8", "from(18)")
        .with(|| NiceU8::from(18_u8)),

    Bench::spacer(),

    Bench::new("dactyl::NiceU16", "from(0)")
        .with(|| NiceU16::from(0_u16)),

    Bench::new("dactyl::NiceU16", "from(18)")
        .with(|| NiceU16::from(18_u16))
);

The above would give you a result readout like:

dactyl::NiceU8::from(0)     2.36 ns   
dactyl::NiceU8::from(18)    1.92 ns   

dactyl::NiceU16::from(0)    4.46 ns   
dactyl::NiceU16::from(18)   4.47 ns

License

See also: CREDITS.md

Copyright © 2022 Blobfolio, LLC <hello@blobfolio.com>

This work is free. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2.

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004

Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>

Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. You just DO WHAT THE FUCK YOU WANT TO.

Dependencies

~0.9–1.6MB
~36K SLoC