Skip to content

Commit 04fcede

Browse files
authored
Merge pull request #1453 from rust-lang/runtime-cli
Runtime benchmarks CLI and documentation improvements
2 parents 9e8c08f + 49bab72 commit 04fcede

File tree

14 files changed

+159
-60
lines changed

14 files changed

+159
-60
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ Additional documentation on running and setting up the frontend and backend can
88
be found in the `README` files in the `collector` and `site` directories.
99

1010
Additional documentation on the benchmark programs can be found in the `README`
11-
file in the `collector/benchmarks` directory.
11+
file in the `collector/compile-benchmarks` and `collector/runtime-benchmarks` directories.

collector/benchlib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ serde_json = "1.0.83"
1313
log = "0.4.17"
1414
env_logger = "0.9.0"
1515
clap = { version = "3.2", features = ["derive"] }
16+
libc = "0.2"
1617

1718
[target.'cfg(unix)'.dependencies]
1819
perf-event = "0.4.7"

collector/benchlib/src/benchmark.rs

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::cli::{parse_cli, Args, BenchmarkArgs};
22
use crate::measure::benchmark_function;
33
use crate::messages::BenchmarkResult;
4+
use crate::process::raise_process_priority;
45
use log::LevelFilter;
56
use std::collections::HashMap;
67

@@ -14,9 +15,16 @@ pub fn benchmark_suite<F: FnOnce(&mut BenchmarkSuite)>(define_func: F) {
1415
suite.run().expect("Benchmark suite has failed");
1516
}
1617

18+
/// Type-erased function that performs a benchmark.
19+
struct BenchmarkWrapper {
20+
func: Box<dyn Fn() -> anyhow::Result<BenchmarkResult>>,
21+
}
22+
23+
type BenchmarkMap = HashMap<&'static str, BenchmarkWrapper>;
24+
1725
#[derive(Default)]
1826
pub struct BenchmarkSuite {
19-
benchmarks: HashMap<&'static str, BenchmarkWrapper>,
27+
benchmarks: BenchmarkMap,
2028
}
2129

2230
impl BenchmarkSuite {
@@ -48,36 +56,47 @@ impl BenchmarkSuite {
4856
/// Execute the benchmark suite. It will parse CLI arguments and decide what to do based on
4957
/// them.
5058
pub fn run(self) -> anyhow::Result<()> {
59+
raise_process_priority();
60+
5161
let args = parse_cli()?;
5262
match args {
5363
Args::Benchmark(args) => {
54-
self.run_benchmark(args)?;
64+
run_benchmark(args, self.benchmarks)?;
5565
}
5666
}
5767

5868
Ok(())
5969
}
70+
}
6071

61-
fn run_benchmark(self, args: BenchmarkArgs) -> anyhow::Result<()> {
62-
let mut items: Vec<_> = self.benchmarks.into_iter().collect();
63-
items.sort_unstable_by_key(|item| item.0);
72+
fn run_benchmark(args: BenchmarkArgs, benchmarks: BenchmarkMap) -> anyhow::Result<()> {
73+
let mut items: Vec<(&'static str, BenchmarkWrapper)> = benchmarks
74+
.into_iter()
75+
.filter(|(name, _)| passes_filter(name, args.exclude.as_deref(), args.include.as_deref()))
76+
.collect();
77+
items.sort_unstable_by_key(|item| item.0);
6478

65-
let mut results: Vec<BenchmarkResult> = Vec::with_capacity(items.len());
66-
for (name, def) in items {
67-
for i in 0..args.iterations {
68-
let result = (def.func)()?;
69-
log::info!("Benchmark (run {i}) `{}` completed: {:?}", name, result);
70-
results.push(result);
71-
}
79+
let mut results: Vec<BenchmarkResult> = Vec::with_capacity(items.len());
80+
for (name, def) in items {
81+
for i in 0..args.iterations {
82+
let result = (def.func)()?;
83+
log::info!("Benchmark (run {i}) `{name}` completed: {result:?}");
84+
results.push(result);
7285
}
73-
74-
println!("{}", serde_json::to_string(&results)?);
75-
Ok(())
7686
}
87+
88+
println!("{}", serde_json::to_string(&results)?);
89+
Ok(())
7790
}
7891

79-
struct BenchmarkWrapper {
80-
func: Box<dyn Fn() -> anyhow::Result<BenchmarkResult>>,
92+
/// Tests if the name of the benchmark passes through the include and exclude filter flags.
93+
fn passes_filter(name: &str, exclude: Option<&str>, include: Option<&str>) -> bool {
94+
match (exclude, include) {
95+
(Some(exclude), Some(include)) => name.starts_with(include) && !name.starts_with(exclude),
96+
(None, Some(include)) => name.starts_with(include),
97+
(Some(exclude), None) => !name.starts_with(&exclude),
98+
(None, None) => true,
99+
}
81100
}
82101

83102
/// Copied from `iai`, so that we don't have to use unstable features.

collector/benchlib/src/cli.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ pub struct BenchmarkArgs {
1111
/// How many times should each benchmark be repeated.
1212
#[clap(long, default_value = "5")]
1313
pub iterations: u32,
14+
15+
/// Exclude all benchmarks matching a prefix in this comma-separated list
16+
#[clap(long)]
17+
pub exclude: Option<String>,
18+
19+
/// Include only benchmarks matching a prefix in this comma-separated list
20+
#[clap(long)]
21+
pub include: Option<String>,
1422
}
1523

1624
pub fn parse_cli() -> anyhow::Result<Args> {

collector/benchlib/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
//! This library defines an API for performing benchmarks of Rust code. It is tailored for the
2-
//! use-case of `rustc-perf`, that's why we don't use e.g. `criterion` or `iai`.
1+
//! This library defines an API for performing benchmarks of Rust code and various other utilities
2+
//! for measuring and benchmarking. It is tailored for the use-case of `rustc-perf`, that's why we
3+
//! don't use e.g. `criterion` or `iai`.
34
//!
45
//! We want to be able to define short benchmarks in code, measure specific perf. counters and most
56
//! importantly, consume the benchmark results in a programmatic way.
@@ -16,3 +17,4 @@ pub mod benchmark;
1617
mod cli;
1718
pub mod measure;
1819
pub mod messages;
20+
pub mod process;

collector/benchlib/src/process.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#[cfg(unix)]
2+
pub fn raise_process_priority() {
3+
unsafe {
4+
// Try to reduce jitter in wall time by increasing our priority to the
5+
// maximum
6+
for i in (1..21).rev() {
7+
let r = libc::setpriority(libc::PRIO_PROCESS as _, libc::getpid() as libc::id_t, -i);
8+
if r == 0 {
9+
break;
10+
}
11+
}
12+
}
13+
}
14+
15+
#[cfg(windows)]
16+
pub fn raise_process_priority() {}

collector/compile-benchmarks/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
# The Benchmark Suite
1+
# The Compile-time Benchmark Suite
22

3-
This file describes the programs in the benchmark suite and explains why they
3+
This file describes the programs in the compile-time benchmark suite and explains why they
44
were included.
55

66
The suite changes over time. Sometimes the code for a benchmark is updated, in
77
which case a small suffix will be added (starting with "-2", then "-3", and so
88
on.)
99

10-
There are three categories of benchmarks, **Primary**, **Secondary**, and
10+
There are three categories of compile-time benchmarks, **Primary**, **Secondary**, and
1111
**Stable**.
1212

1313
## Primary
@@ -198,7 +198,7 @@ Rust code being written today.
198198
applies correctly, e.g. `target/release/collector bench_local +nightly
199199
--id Test --profiles=Check --scenarios=IncrPatched
200200
--include=$NEW_BENCHMARK`
201-
- Add the new entry to `collector/benchmarks/README.md`.
201+
- Add the new entry to `collector/compile-benchmarks/README.md`.
202202
- `git add` the `Cargo.lock` file, if it's not already part of the
203203
benchmark's committed code.
204204
- If the benchmark has a `.gitignore` file that contains `Cargo.lock`,
@@ -232,7 +232,7 @@ Rust code being written today.
232232
- In the first commit just remove the old code.
233233
- Do this with `git rm -r` on the directory.
234234
- In the second commit do everything else.
235-
- Remove the entry from `collector/benchmarks/README.md`.
235+
- Remove the entry from `collector/compile-benchmarks/README.md`.
236236
- `git grep` for occurrences of the old benchmark name (e.g. in
237237
`.github/workflows/ci.yml` or `ci/check-*.sh`) and see if anything needs
238238
changing... usually not.

collector/runtime-benchmarks/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# The Runtime Benchmark Suite
2+
This directory contains various pieces of code for which we measure how fast do they execute
3+
when they are compiled with a specific version of `rustc`.
4+
5+
The benchmarks are located in crates that are part of the `runtime-benchmarks` workspace. Each crate
6+
contains a set of benchmarks defined using named closures.
7+
8+
Benchmarks are divided into sub-crates so that some benchmarks can use various versions of dependency
9+
crates and also so that they are grouped together by a relevant area (e.g. hashmap benchmarks).

0 commit comments

Comments
 (0)