Skip to content

Commit a987f32

Browse files
committed
Update documentation and terminology of runtime benchmarks
1 parent 5f8b9d5 commit a987f32

File tree

7 files changed

+57
-51
lines changed

7 files changed

+57
-51
lines changed

collector/benchlib/src/benchmark.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::cli::{parse_cli, Args, BenchmarkArgs};
2-
use crate::comm::messages::{BenchmarkMeasurement, BenchmarkMessage, BenchmarkStats};
2+
use crate::comm::messages::{BenchmarkMessage, BenchmarkResult, BenchmarkStats};
33
use crate::comm::output_message;
44
use crate::measure::benchmark_function;
55
use crate::process::raise_process_priority;
@@ -14,9 +14,9 @@ pub fn benchmark_suite<F: FnOnce(&mut BenchmarkSuite)>(define_func: F) {
1414
suite.run().expect("Benchmark suite has failed");
1515
}
1616

17-
/// Type-erased function that performs a benchmark.
17+
/// Type-erased function that executes a single benchmark.
1818
struct BenchmarkWrapper {
19-
func: Box<dyn Fn() -> anyhow::Result<BenchmarkMeasurement>>,
19+
func: Box<dyn Fn() -> anyhow::Result<BenchmarkStats>>,
2020
}
2121

2222
type BenchmarkMap = HashMap<&'static str, BenchmarkWrapper>;
@@ -82,18 +82,17 @@ fn run_benchmark(args: BenchmarkArgs, benchmarks: BenchmarkMap) -> anyhow::Resul
8282
let mut stdout = std::io::stdout().lock();
8383

8484
for (name, def) in items {
85-
let mut measurements: Vec<BenchmarkMeasurement> =
86-
Vec::with_capacity(args.iterations as usize);
85+
let mut stats: Vec<BenchmarkStats> = Vec::with_capacity(args.iterations as usize);
8786
for i in 0..args.iterations {
88-
let measurement = (def.func)()?;
89-
log::info!("Benchmark (run {i}) `{name}` completed: {measurement:?}");
90-
measurements.push(measurement);
87+
let benchmark_stats = (def.func)()?;
88+
log::info!("Benchmark (run {i}) `{name}` completed: {benchmark_stats:?}");
89+
stats.push(benchmark_stats);
9190
}
9291
output_message(
9392
&mut stdout,
94-
BenchmarkMessage::Stats(BenchmarkStats {
93+
BenchmarkMessage::Result(BenchmarkResult {
9594
name: name.to_string(),
96-
measurements,
95+
stats,
9796
}),
9897
)?;
9998
}

collector/benchlib/src/comm/messages.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ use std::time::Duration;
55

66
#[derive(Debug, serde::Serialize, serde::Deserialize)]
77
pub enum BenchmarkMessage {
8-
Stats(BenchmarkStats),
8+
Result(BenchmarkResult),
99
}
1010

11-
/// Results of several measurements of a single benchmark.
11+
/// Stats gathered by several executions of a single benchmark.
1212
#[derive(Debug, serde::Serialize, serde::Deserialize)]
13-
pub struct BenchmarkStats {
13+
pub struct BenchmarkResult {
1414
pub name: String,
15-
pub measurements: Vec<BenchmarkMeasurement>,
15+
pub stats: Vec<BenchmarkStats>,
1616
}
1717

18-
/// Results of a single benchmark execution.
18+
/// The stats gathered by a single benchmark execution.
1919
#[derive(Debug, serde::Serialize, serde::Deserialize)]
20-
pub struct BenchmarkMeasurement {
20+
pub struct BenchmarkStats {
2121
pub cycles: u64,
2222
pub instructions: u64,
2323
pub branch_misses: u64,

collector/benchlib/src/measure/perf_counter/unix.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::benchmark::black_box;
2-
use crate::comm::messages::BenchmarkMeasurement;
2+
use crate::comm::messages::BenchmarkStats;
33
use perf_event::events::Hardware;
44
use perf_event::{Builder, Counter, Group};
55
use std::time::Instant;
@@ -18,7 +18,7 @@ struct Counters {
1818
pub fn benchmark_function<F: Fn() -> Bench + 'static, R, Bench: FnOnce() -> R + 'static>(
1919
name: &'static str,
2020
benchmark_constructor: F,
21-
) -> anyhow::Result<BenchmarkMeasurement> {
21+
) -> anyhow::Result<BenchmarkStats> {
2222
let mut group = create_group()?;
2323
let counters = prepare_counters(&mut group)?;
2424

@@ -48,7 +48,7 @@ pub fn benchmark_function<F: Fn() -> Bench + 'static, R, Bench: FnOnce() -> R +
4848
// Try to avoid optimizing the result out.
4949
black_box(output);
5050

51-
let result = BenchmarkMeasurement {
51+
let result = BenchmarkStats {
5252
cycles: measurement[&counters.cycles],
5353
instructions: measurement[&counters.instructions],
5454
branch_misses: measurement[&counters.branch_misses],
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::comm::messages::BenchmarkMeasurement;
1+
use crate::comm::messages::BenchmarkStats;
22

3-
pub fn benchmark_function<F: FnOnce() -> R, R>(_func: F) -> anyhow::Result<BenchmarkMeasurement> {
3+
pub fn benchmark_function<F: FnOnce() -> R, R>(_func: F) -> anyhow::Result<BenchmarkStats> {
44
panic!("Runtime benchmarking is not supported on Windows");
55
}

collector/src/runtime/benchmark.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,23 @@ use core::result::Result::Ok;
66
use std::path::{Path, PathBuf};
77
use std::process::Command;
88

9+
/// A binary that defines several benchmarks using the `benchmark_suite` function from `benchlib`.
910
#[derive(Debug)]
10-
pub struct BenchmarkBinary {
11-
pub path: PathBuf,
11+
pub struct BenchmarkSuite {
12+
pub binary: PathBuf,
1213
pub benchmark_names: Vec<String>,
1314
}
1415

15-
impl BenchmarkBinary {
16+
impl BenchmarkSuite {
1617
pub fn name(&self) -> &str {
17-
self.path.file_name().unwrap().to_str().unwrap()
18+
self.binary.file_name().unwrap().to_str().unwrap()
1819
}
1920
}
2021

22+
/// A collection of benchmark suites gathered from a directory.
2123
#[derive(Debug)]
2224
pub struct BenchmarkDatabase {
23-
pub binaries: Vec<BenchmarkBinary>,
25+
pub suites: Vec<BenchmarkSuite>,
2426
}
2527

2628
impl BenchmarkDatabase {
@@ -40,9 +42,9 @@ impl BenchmarkDatabase {
4042
}
4143

4244
fn benchmark_names(&self) -> impl Iterator<Item = &str> {
43-
self.binaries
45+
self.suites
4446
.iter()
45-
.flat_map(|binary| binary.benchmark_names.iter().map(|n| n.as_ref()))
47+
.flat_map(|suite| suite.benchmark_names.iter().map(|n| n.as_ref()))
4648
}
4749
}
4850

@@ -57,8 +59,10 @@ impl BenchmarkFilter {
5759
}
5860
}
5961

60-
/// Parse Cargo JSON output and find all compiled binaries.
61-
/// Then execute each benchmark with the `list-benchmarks` command to find out its benchmark names.
62+
/// Parse Cargo JSON output to find all compiled binaries.
63+
/// We assume that each binary defines a benchmark suite using `benchlib`.
64+
/// We then execute each benchmark suite with the `list-benchmarks` command to find out its
65+
/// benchmark names.
6266
pub fn discover_benchmarks(cargo_stdout: &[u8]) -> anyhow::Result<BenchmarkDatabase> {
6367
let mut binaries = vec![];
6468

@@ -75,8 +79,8 @@ pub fn discover_benchmarks(cargo_stdout: &[u8]) -> anyhow::Result<BenchmarkDatab
7579
path.display()
7680
)
7781
})?;
78-
binaries.push(BenchmarkBinary {
79-
path,
82+
binaries.push(BenchmarkSuite {
83+
binary: path,
8084
benchmark_names: benchmarks,
8185
});
8286
}
@@ -86,10 +90,10 @@ pub fn discover_benchmarks(cargo_stdout: &[u8]) -> anyhow::Result<BenchmarkDatab
8690
}
8791
}
8892

89-
binaries.sort_unstable_by(|a, b| a.path.cmp(&b.path));
93+
binaries.sort_unstable_by(|a, b| a.binary.cmp(&b.binary));
9094
log::debug!("Found binaries: {:?}", binaries);
9195

92-
Ok(BenchmarkDatabase { binaries })
96+
Ok(BenchmarkDatabase { suites: binaries })
9397
}
9498

9599
/// Uses the `list-benchmarks` command from `benchlib` to find the benchmark names from the given

collector/src/runtime/mod.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod benchmark;
22

33
use crate::benchmark::profile::Profile;
44
use crate::toolchain::{get_local_toolchain, LocalToolchain};
5-
use benchlib::comm::messages::{BenchmarkMeasurement, BenchmarkMessage, BenchmarkStats};
5+
use benchlib::comm::messages::{BenchmarkMessage, BenchmarkResult, BenchmarkStats};
66
use std::io::{BufRead, BufReader};
77
use std::path::{Path, PathBuf};
88
use std::process::{Command, Stdio};
@@ -32,25 +32,25 @@ pub fn bench_runtime(
3232
);
3333

3434
let mut benchmark_index = 0;
35-
for binary in benchmark_db.binaries {
36-
for message in execute_runtime_benchmark(&binary.path, &filter)? {
35+
for binary in benchmark_db.suites {
36+
for message in execute_runtime_benchmark(&binary.binary, &filter)? {
3737
let message = message.map_err(|err| {
3838
anyhow::anyhow!(
3939
"Cannot parse BenchmarkMessage from benchmark {}: {err:?}",
40-
binary.path.display()
40+
binary.binary.display()
4141
)
4242
})?;
4343
match message {
44-
BenchmarkMessage::Stats(stats) => {
44+
BenchmarkMessage::Result(result) => {
4545
benchmark_index += 1;
4646
println!(
4747
"Finished {}/{} ({}/{})",
4848
binary.name(),
49-
stats.name,
49+
result.name,
5050
benchmark_index,
5151
filtered
5252
);
53-
print_stats(&stats);
53+
print_stats(&result);
5454
}
5555
}
5656
}
@@ -121,12 +121,12 @@ fn calculate_mean<I: Iterator<Item = f64> + Clone>(iter: I) -> f64 {
121121
sum / count as f64
122122
}
123123

124-
fn print_stats(stats: &BenchmarkStats) {
125-
fn print_metric<F: Fn(&BenchmarkMeasurement) -> u64>(stats: &BenchmarkStats, name: &str, f: F) {
126-
let mean = calculate_mean(stats.measurements.iter().map(&f).map(|v| v as f64));
124+
fn print_stats(result: &BenchmarkResult) {
125+
fn print_metric<F: Fn(&BenchmarkStats) -> u64>(result: &BenchmarkResult, name: &str, f: F) {
126+
let mean = calculate_mean(result.stats.iter().map(&f).map(|v| v as f64));
127127
let stddev = calculate_mean(
128-
stats
129-
.measurements
128+
result
129+
.stats
130130
.iter()
131131
.map(&f)
132132
.map(|v| (v as f64 - mean).powf(2.0)),
@@ -137,9 +137,9 @@ fn print_stats(stats: &BenchmarkStats) {
137137
println!("{name:>20}: {:>16} (+/- {:>8})", mean as u64, stddev as u64);
138138
}
139139

140-
print_metric(stats, "Instructions", |m| m.instructions);
141-
print_metric(stats, "Cycles", |m| m.cycles);
142-
print_metric(stats, "Wall time [us]", |m| m.wall_time.as_micros() as u64);
143-
print_metric(stats, "Branch misses", |m| m.branch_misses);
144-
print_metric(stats, "Cache misses", |m| m.cache_misses);
140+
print_metric(result, "Instructions", |m| m.instructions);
141+
print_metric(result, "Cycles", |m| m.cycles);
142+
print_metric(result, "Wall time [us]", |m| m.wall_time.as_micros() as u64);
143+
print_metric(result, "Branch misses", |m| m.branch_misses);
144+
print_metric(result, "Cache misses", |m| m.cache_misses);
145145
}

docs/glossary.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ The following is a glossary of domain specific terminology. Although benchmarks
3636
* **relevant test result comparison**: a test result comparison can be significant but still not be relevant (i.e., worth paying attention to). Relevance is a factor of the test result comparison's significance and magnitude. Comparisons are considered relevant if they are significant and have at least a small magnitude .
3737
* **test result comparison magnitude**: how "large" the delta is between the two test result's under comparison. This is determined by the average of two factors: the absolute size of the change (i.e., a change of 5% is larger than a change of 1%) and the amount above the significance threshold (i.e., a change that is 5x the significance threshold is larger than a change 1.5x the significance threshold).
3838

39+
## Runtime benchmarks
40+
* **benchmark suite**: a collection of individual benchmarks that is defined in a single binary.
41+
3942
## Other
4043

4144
* **bootstrap**: the process of building the compiler from a previous version of the compiler

0 commit comments

Comments
 (0)