Infra for "unit" benchmarking

This commit is contained in:
Aleksey Kladov 2021-02-09 19:29:40 +03:00
parent 9ea2c96ddd
commit 4b1279d0b1
8 changed files with 102 additions and 4001 deletions

View file

@ -0,0 +1,28 @@
//! Generates large snippets of Rust code for usage in the benchmarks.
use stdx::format_to;
pub fn big_struct() -> String {
let n = 1_000;
let mut buf = "pub struct RegisterBlock {".to_string();
for i in 0..n {
format_to!(buf, " /// Doc comment for {}.\n", i);
format_to!(buf, " pub s{}: S{},\n", i, i);
}
buf.push_str("}\n\n");
for i in 0..n {
format_to!(
buf,
"
#[repr(transparent)]
struct S{} {{
field: u32,
}}",
i
);
}
buf
}

View file

@ -8,6 +8,7 @@
#[macro_use]
pub mod mark;
pub mod bench_fixture;
mod fixture;
use std::{
@ -16,6 +17,7 @@ use std::{
path::PathBuf,
};
use profile::StopWatch;
use serde_json::Value;
use stdx::lines_with_ends;
use text_size::{TextRange, TextSize};
@ -406,3 +408,44 @@ pub fn format_diff(chunks: Vec<dissimilar::Chunk>) -> String {
}
buf
}
/// Utility for writing benchmark tests.
///
/// A benchmark test looks like this:
///
/// ```
/// #[test]
/// fn benchmark_foo() {
/// if skip_slow_tests() { return; }
///
/// let data = bench_fixture::some_fixture();
/// let analysis = some_setup();
///
/// let hash = {
/// let _b = bench("foo");
/// actual_work(analysis)
/// };
/// assert_eq!(hash, 92);
/// }
/// ```
///
/// * We skip benchmarks by default, to save time.
/// Ideal benchmark time is 800 -- 1500 ms in debug.
/// * We don't count preparation as part of the benchmark
/// * The benchmark itself returns some kind of numeric hash.
/// The hash is used as a sanity check that some code is actually run.
/// Otherwise, it's too easy to win the benchmark by just doing nothing.
pub fn bench(label: &'static str) -> impl Drop {
struct Bencher {
sw: StopWatch,
label: &'static str,
}
impl Drop for Bencher {
fn drop(&mut self) {
eprintln!("{}: {}", self.label, self.sw.elapsed())
}
}
Bencher { sw: StopWatch::start(), label }
}