Skip to content

Commit e7f117f

Browse files
committed
Overhaul how the rustc benchmark works.
Currently the `rustc` benchmark is handled like a normal benchmark in some ways, and handled very differently in others. This results in various non-obvious special cases. This commit improves things. - Adds a `--bench-rustc` option to `bench_local` and `bench_next`, which makes the rustc benchmark opt-in. - Omits the rustc benchmark from `--include`/`--exclude` handling. - Calls it the "special rustc benchmark", in contrast to the "normal benchmarks". - Handles it directly in `bench()`, avoiding a bunch of awkward special-casing code. - Adds an `eprintln!` to make it more obvious when it starts running. - Cleans up some unnecessary string conversions in `bench()`.
1 parent 6000d6a commit e7f117f

File tree

6 files changed

+91
-57
lines changed

6 files changed

+91
-57
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ jobs:
6464
strategy:
6565
matrix:
6666
BENCH_INCLUDE_EXCLUDE_OPTS: [
67-
"--exclude webrender-wrench,style-servo,cargo,rustc",
68-
"--include webrender-wrench,style-servo,cargo --exclude rustc",
67+
"--exclude webrender-wrench,style-servo,cargo",
68+
"--include webrender-wrench,style-servo,cargo",
6969
]
7070
PROFILE_KINDS: [
7171
"Check,Doc,Debug",

collector/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ The following options alter the behaviour of the `bench_local` subcommand.
107107
comma-separated list of benchmark names. When this option is specified, a
108108
benchmark is included in the run only if its name matches one or more of the
109109
given names.
110+
- `--bench-rustc`: there is a special `rustc` benchmark that involves
111+
downloading a recent Rust compiler and measuring the time taken to compile
112+
it. This benchmark works very differently to all the other benchmarks. For
113+
example, `--runs` and `--builds` don't affect it, and the given `ID` is used
114+
as the `rust-lang/rust` ref (falling back to `HEAD` if the `ID` is not a
115+
valid ref). It is for advanced and CI use only. This option enables it.
110116
- `--runs $RUNS`: the run kinds to be benchmarked. The possible choices are one
111117
or more (comma-separated) of `Full`, `IncrFull`, `IncrUnchanged`,
112118
`IncrPatched`, and `All`. The default is `All`. Note that `IncrFull` is

collector/collect.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ while : ; do
2626
rm todo-artifacts
2727
touch todo-artifacts
2828

29-
target/release/collector bench_next $SITE_URL --self-profile --db $DATABASE;
29+
target/release/collector bench_next $SITE_URL --self-profile --bench-rustc --db $DATABASE;
3030
echo finished run at `date`;
3131
done

collector/src/execute.rs

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -571,10 +571,6 @@ pub trait Processor {
571571
fn finished_first_collection(&mut self, _: ProfileKind) -> bool {
572572
false
573573
}
574-
575-
fn measure_rustc(&mut self, _: Compiler<'_>) -> anyhow::Result<()> {
576-
Ok(())
577-
}
578574
}
579575

580576
pub struct BenchProcessor<'a> {
@@ -722,6 +718,16 @@ impl<'a> BenchProcessor<'a> {
722718
self.rt
723719
.block_on(async move { while let Some(()) = buf.next().await {} });
724720
}
721+
722+
pub fn measure_rustc(&mut self, compiler: Compiler<'_>) -> anyhow::Result<()> {
723+
rustc::measure(
724+
self.rt,
725+
self.conn,
726+
compiler,
727+
self.artifact,
728+
self.artifact_row_id,
729+
)
730+
}
725731
}
726732

727733
struct Upload(std::process::Child, tempfile::NamedTempFile);
@@ -897,16 +903,6 @@ impl<'a> Processor for BenchProcessor<'a> {
897903
}
898904
}
899905
}
900-
901-
fn measure_rustc(&mut self, compiler: Compiler<'_>) -> anyhow::Result<()> {
902-
rustc::measure(
903-
self.rt,
904-
self.conn,
905-
compiler,
906-
self.artifact,
907-
self.artifact_row_id,
908-
)
909-
}
910906
}
911907

912908
pub struct ProfileProcessor<'a> {
@@ -1231,15 +1227,6 @@ impl<'a> Processor for ProfileProcessor<'a> {
12311227

12321228
impl Benchmark {
12331229
pub fn new(name: String, path: PathBuf) -> anyhow::Result<Self> {
1234-
if name == "rustc" {
1235-
return Ok(Benchmark {
1236-
name: BenchmarkName(name),
1237-
path,
1238-
patches: vec![],
1239-
config: BenchmarkConfig::default(),
1240-
});
1241-
}
1242-
12431230
let mut patches = vec![];
12441231
for entry in fs::read_dir(&path)? {
12451232
let entry = entry?;
@@ -1359,10 +1346,6 @@ impl Benchmark {
13591346
) -> anyhow::Result<()> {
13601347
let iterations = iterations.unwrap_or(self.config.runs);
13611348

1362-
if self.name.0 == "rustc" {
1363-
return processor.measure_rustc(compiler).context("measure rustc");
1364-
}
1365-
13661349
if self.config.disabled || profile_kinds.is_empty() {
13671350
eprintln!("Skipping {}: disabled", self.name);
13681351
bail!("disabled benchmark");

collector/src/execute/rustc.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@ use std::{collections::HashMap, process::Command};
1515
use std::{path::Path, time::Duration};
1616
use tokio::runtime::Runtime;
1717

18+
/// Measure the special rustc benchmark.
1819
pub fn measure(
1920
rt: &mut Runtime,
2021
conn: &mut dyn database::Connection,
2122
compiler: Compiler<'_>,
2223
artifact: &database::ArtifactId,
2324
aid: database::ArtifactIdNumber,
2425
) -> anyhow::Result<()> {
26+
eprintln!("Running rustc");
27+
2528
checkout(&artifact).context("checking out rust-lang/rust")?;
2629

2730
record(rt, conn, compiler, artifact, aid)?;

collector/src/main.rs

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ where
183183
Ok(v)
184184
}
185185

186-
fn n_benchmarks_remaining(n: usize) -> String {
186+
fn n_normal_benchmarks_remaining(n: usize) -> String {
187187
let suffix = if n == 1 { "" } else { "s" };
188-
format!("{} benchmark{} remaining", n, suffix)
188+
format!("{} normal benchmark{} remaining", n, suffix)
189189
}
190190

191191
struct BenchmarkErrors(usize);
@@ -213,6 +213,7 @@ fn bench(
213213
artifact_id: &ArtifactId,
214214
profile_kinds: &[ProfileKind],
215215
scenario_kinds: &[ScenarioKind],
216+
bench_rustc: bool,
216217
compiler: Compiler<'_>,
217218
benchmarks: &[Benchmark],
218219
iterations: Option<usize>,
@@ -231,10 +232,13 @@ fn bench(
231232
}
232233
}
233234

234-
let steps = benchmarks
235+
let mut steps = benchmarks
235236
.iter()
236237
.map(|b| b.name.to_string())
237238
.collect::<Vec<_>>();
239+
if bench_rustc {
240+
steps.push("rustc".to_string());
241+
}
238242

239243
// Make sure there is no observable time when the artifact ID is available
240244
// but the in-progress steps are not.
@@ -249,57 +253,87 @@ fn bench(
249253

250254
let start = Instant::now();
251255
let mut skipped = false;
252-
for (nth_benchmark, benchmark) in benchmarks.iter().enumerate() {
253-
let is_fresh =
254-
rt.block_on(conn.collector_start_step(artifact_row_id, &benchmark.name.to_string()));
256+
257+
let mut measure_and_record = |benchmark_name: &execute::BenchmarkName,
258+
benchmark_supports_stable: bool,
259+
print_intro: &dyn Fn(),
260+
measure: &dyn Fn(
261+
&mut execute::BenchProcessor,
262+
) -> Result<(), anyhow::Error>| {
263+
let is_fresh = rt.block_on(conn.collector_start_step(artifact_row_id, &benchmark_name.0));
255264
if !is_fresh {
256265
skipped = true;
257-
eprintln!("skipping {} -- already benchmarked", benchmark.name);
258-
continue;
266+
eprintln!("skipping {} -- already benchmarked", benchmark_name);
267+
return;
259268
}
260269
let mut tx = rt.block_on(conn.transaction());
261270
rt.block_on(
262271
tx.conn()
263-
.record_benchmark(benchmark.name.0.as_str(), Some(benchmark.supports_stable())),
264-
);
265-
eprintln!(
266-
"{}",
267-
n_benchmarks_remaining(benchmarks.len() - nth_benchmark)
272+
.record_benchmark(&benchmark_name.0, Some(benchmark_supports_stable)),
268273
);
274+
print_intro();
269275

270276
let mut processor = execute::BenchProcessor::new(
271277
rt,
272278
tx.conn(),
273-
&benchmark.name,
279+
benchmark_name,
274280
&artifact_id,
275281
artifact_row_id,
276282
is_self_profile,
277283
);
278-
let result = benchmark.measure(
279-
&mut processor,
280-
profile_kinds,
281-
scenario_kinds,
282-
compiler,
283-
iterations,
284-
);
284+
let result = measure(&mut processor);
285285
if let Err(s) = result {
286286
eprintln!(
287287
"collector error: Failed to benchmark '{}', recorded: {:#}",
288-
benchmark.name, s
288+
benchmark_name, s
289289
);
290290
errors.incr();
291291
rt.block_on(tx.conn().record_error(
292292
artifact_row_id,
293-
benchmark.name.0.as_str(),
293+
&benchmark_name.0,
294294
&format!("{:?}", s),
295295
));
296296
};
297297
rt.block_on(
298298
tx.conn()
299-
.collector_end_step(artifact_row_id, &benchmark.name.to_string()),
299+
.collector_end_step(artifact_row_id, &benchmark_name.0),
300300
);
301301
rt.block_on(tx.commit()).expect("committed");
302+
};
303+
304+
// Normal benchmarks.
305+
for (nth_benchmark, benchmark) in benchmarks.iter().enumerate() {
306+
measure_and_record(
307+
&benchmark.name,
308+
benchmark.supports_stable(),
309+
&|| {
310+
eprintln!(
311+
"{}",
312+
n_normal_benchmarks_remaining(benchmarks.len() - nth_benchmark)
313+
)
314+
},
315+
&|processor| {
316+
benchmark.measure(
317+
processor,
318+
profile_kinds,
319+
scenario_kinds,
320+
compiler,
321+
iterations,
322+
)
323+
},
324+
)
302325
}
326+
327+
// The special rustc benchmark, if requested.
328+
if bench_rustc {
329+
measure_and_record(
330+
&execute::BenchmarkName("rustc".to_string()),
331+
/* supports_stable */ false,
332+
&|| eprintln!("Special benchmark commencing (due to `--bench-rustc`)"),
333+
&|processor| processor.measure_rustc(compiler).context("measure rustc"),
334+
);
335+
}
336+
303337
let end = start.elapsed();
304338

305339
eprintln!(
@@ -373,7 +407,6 @@ fn get_benchmarks(
373407

374408
paths.push((path, name));
375409
}
376-
paths.push((PathBuf::from("rustc"), String::from("rustc")));
377410

378411
let mut includes = include.map(|list| list.split(',').collect::<HashSet<_>>());
379412
let mut excludes = exclude.map(|list| list.split(',').collect::<HashSet<_>>());
@@ -683,7 +716,7 @@ fn profile(
683716
check_measureme_installed().unwrap();
684717
}
685718
for (i, benchmark) in benchmarks.iter().enumerate() {
686-
eprintln!("{}", n_benchmarks_remaining(benchmarks.len() - i));
719+
eprintln!("{}", n_normal_benchmarks_remaining(benchmarks.len() - i));
687720
let mut processor = execute::ProfileProcessor::new(profiler, out_dir, id);
688721
let result = benchmark.measure(
689722
&mut processor,
@@ -742,6 +775,8 @@ fn main_result() -> anyhow::Result<i32> {
742775
(@arg INCLUDE: --include +takes_value
743776
"Include only benchmarks that are listed in\n\
744777
this comma-separated list of patterns")
778+
(@arg BENCH_RUSTC: --("bench-rustc")
779+
"Run the special `rustc` benchmark")
745780
(@arg RUNS: --runs +takes_value
746781
"One or more (comma-separated) of: 'Full',\n\
747782
'IncrFull', 'IncrUnchanged', 'IncrPatched', 'All'")
@@ -752,13 +787,15 @@ fn main_result() -> anyhow::Result<i32> {
752787
)
753788

754789
(@subcommand bench_next =>
755-
(about: "Benchmarks the next commit for perf.rust-lang.org")
790+
(about: "Benchmarks the next commit for perf.rust-lang.org, including the special `rustc` benchmark")
756791

757792
// Mandatory arguments
758793
(@arg SITE_URL: +required +takes_value "Site URL")
759794

760795
// Options
761796
(@arg DB: --db +takes_value "Database output file")
797+
(@arg BENCH_RUSTC: --("bench-rustc")
798+
"Run the special `rustc` benchmark")
762799
(@arg SELF_PROFILE: --("self-profile") "Collect self-profile data")
763800
)
764801

@@ -868,6 +905,7 @@ fn main_result() -> anyhow::Result<i32> {
868905
let db = sub_m.value_of("DB").unwrap_or(default_db);
869906
let exclude = sub_m.value_of("EXCLUDE");
870907
let include = sub_m.value_of("INCLUDE");
908+
let bench_rustc = sub_m.is_present("BENCH_RUSTC");
871909
let scenario_kinds = scenario_kinds_from_arg(sub_m.value_of("RUNS"))?;
872910
let iterations = iterations_from_arg(sub_m.value_of("ITERATIONS"))?;
873911
let rustdoc = sub_m.value_of("RUSTDOC");
@@ -886,6 +924,7 @@ fn main_result() -> anyhow::Result<i32> {
886924
&ArtifactId::Tag(id.to_string()),
887925
&profile_kinds,
888926
&scenario_kinds,
927+
bench_rustc,
889928
Compiler {
890929
rustc: &rustc,
891930
rustdoc: rustdoc.as_deref(),
@@ -907,6 +946,7 @@ fn main_result() -> anyhow::Result<i32> {
907946

908947
// Options
909948
let db = sub_m.value_of("DB").unwrap_or(default_db);
949+
let bench_rustc = sub_m.is_present("BENCH_RUSTC");
910950
let is_self_profile = sub_m.is_present("SELF_PROFILE");
911951

912952
println!("processing commits");
@@ -941,6 +981,7 @@ fn main_result() -> anyhow::Result<i32> {
941981
&ArtifactId::Commit(commit),
942982
&ProfileKind::all(),
943983
&ScenarioKind::all(),
984+
bench_rustc,
944985
Compiler::from_sysroot(&sysroot),
945986
&benchmarks,
946987
next.runs.map(|v| v as usize),
@@ -1011,6 +1052,7 @@ fn main_result() -> anyhow::Result<i32> {
10111052
&ArtifactId::Tag(toolchain.to_string()),
10121053
&proile_kinds,
10131054
&scenario_kinds,
1055+
/* bench_rustc */ false,
10141056
Compiler {
10151057
rustc: Path::new(rustc.trim()),
10161058
rustdoc: Some(Path::new(rustdoc.trim())),

0 commit comments

Comments
 (0)