Skip to content

Commit

Permalink
Divan benchmarking PoC
Browse files Browse the repository at this point in the history
  • Loading branch information
CrockAgile committed Nov 26, 2023
1 parent 67a7054 commit 8b9e8f1
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ features = ["derive"]
version = "1.0.61"

[dev-dependencies]
divan = "0.1.2"
insta = { version = "1.26.0", default-features = false }

[dev-dependencies.quickcheck]
Expand All @@ -52,5 +53,9 @@ tracing = ["dep:tracing", "dep:tracing-subscriber", "dep:tracing-flame"]
name = "bnf"
harness = false

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

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2.5", features = ["js"] } # needed for rand
105 changes: 105 additions & 0 deletions benches/divan.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
fn main() {
init_tracing();

#[cfg(feature = "tracing")]
let _span = tracing::span!(tracing::Level::DEBUG, "BENCH EXAMPLES").entered();

// Run registered benchmarks.
divan::main();
}

#[cfg(feature = "tracing")]
fn init_tracing() -> impl Drop {
use tracing_flame::FlameLayer;
use tracing_subscriber::{fmt, prelude::*};
let filter_layer = tracing_subscriber::EnvFilter::from_default_env();
let fmt_layer = fmt::Layer::default();
let (flame_layer, _guard) = FlameLayer::with_file("./tracing.folded").unwrap();

tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.with(flame_layer)
.init();

_guard
}

#[cfg(not(feature = "tracing"))]
fn init_tracing() {}

mod examples {
#[divan::bench]
fn parse_postal(bencher: divan::Bencher) {
bencher
.with_inputs(|| {
let input =
std::include_str!("../tests/fixtures/postal_address.terminated.input.bnf");
input
})
.bench_refs(|input| {
input.parse::<bnf::Grammar>().unwrap();
});
}

#[divan::bench]
fn generate_dna(bencher: divan::Bencher) {
bencher
.with_inputs(|| {
let input = "<dna> ::= <base> | <base> <dna>
<base> ::= 'A' | 'C' | 'G' | 'T'";
let grammar: bnf::Grammar = input.parse().unwrap();
grammar
})
.bench_refs(|grammar| {
grammar.generate().unwrap();
});
}

#[divan::bench]
fn parse_polish_calculator(bencher: divan::Bencher) {
let polish_calc_grammar: bnf::Grammar = "<product> ::= <number> | <op> <product> <product>
<op> ::= '+' | '-' | '*' | '/'
<number> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
"
.parse()
.unwrap();

// use pseudo random for consistent metrics
let mut rng: rand::rngs::StdRng = rand::SeedableRng::seed_from_u64(0);
let random_walk_count = 100usize;
let random_walks: Vec<_> = (0..random_walk_count)
.map(|_| polish_calc_grammar.generate_seeded(&mut rng).unwrap())
.collect();

bencher
.with_inputs(|| {
let mut rng = rng.clone();
use rand::seq::SliceRandom;
random_walks.choose(&mut rng).unwrap()
})
.bench_refs(|input| {
let _: Vec<_> = polish_calc_grammar.parse_input(input).collect();
});
}

#[divan::bench]
fn parse_infinite_nullable_grammar(bencher: divan::Bencher) {
let infinite_grammar: bnf::Grammar = "
<a> ::= '' | <b>
<b> ::= <a>"
.parse()
.unwrap();
bencher
.with_inputs(|| {
use rand::Rng;
let mut rng: rand::rngs::StdRng = rand::SeedableRng::seed_from_u64(0);
let parse_count: usize = rng.gen_range(1..100);
parse_count
})
.input_counter(|parse_count| divan::counter::ItemsCount::new(*parse_count))
.bench_values(|parse_count| {
let _: Vec<_> = infinite_grammar.parse_input("").take(parse_count).collect();
})
}
}

0 comments on commit 8b9e8f1

Please sign in to comment.