Skip to content

Commit d58c068

Browse files
committed
Filter compile-time test cases on a more granular level
1 parent 936acb7 commit d58c068

File tree

2 files changed

+104
-22
lines changed

2 files changed

+104
-22
lines changed

collector/src/bin/collector.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ fn profile_compile(
225225
toolchain,
226226
Some(1),
227227
targets,
228+
// We always want to profile everything
229+
&hashbrown::HashSet::new(),
228230
));
229231
eprintln!("Finished benchmark {benchmark_id}");
230232

@@ -1804,11 +1806,8 @@ async fn bench_compile(
18041806
print_intro: &dyn Fn(),
18051807
measure: F,
18061808
) {
1807-
let is_fresh = collector.start_compile_step(conn, benchmark_name).await;
1808-
if !is_fresh {
1809-
eprintln!("skipping {} -- already benchmarked", benchmark_name);
1810-
return;
1811-
}
1809+
collector.start_compile_step(conn, benchmark_name).await;
1810+
18121811
let mut tx = conn.transaction().await;
18131812
let (supports_stable, category) = category.db_representation();
18141813
tx.conn()
@@ -1866,6 +1865,7 @@ async fn bench_compile(
18661865
&shared.toolchain,
18671866
config.iterations,
18681867
&config.targets,
1868+
&collector.measured_compile_test_cases,
18691869
))
18701870
.await
18711871
.with_context(|| anyhow::anyhow!("Cannot compile {}", benchmark.name))

collector/src/compile/benchmark/mod.rs

Lines changed: 99 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::compile::execute::{CargoProcess, Processor};
88
use crate::toolchain::Toolchain;
99
use crate::utils::wait_for_future;
1010
use anyhow::{bail, Context};
11+
use database::selector::CompileTestCase;
1112
use log::debug;
1213
use std::collections::{HashMap, HashSet};
1314
use std::fmt::{Display, Formatter};
@@ -243,6 +244,7 @@ impl Benchmark {
243244
toolchain: &Toolchain,
244245
iterations: Option<usize>,
245246
targets: &[Target],
247+
already_computed: &hashbrown::HashSet<CompileTestCase>,
246248
) -> anyhow::Result<()> {
247249
if self.config.disabled {
248250
eprintln!("Skipping {}: disabled", self.name);
@@ -273,19 +275,62 @@ impl Benchmark {
273275
return Ok(());
274276
}
275277

276-
eprintln!("Preparing {}", self.name);
277-
let mut target_dirs: Vec<((CodegenBackend, Profile, Target), TempDir)> = vec![];
278+
struct BenchmarkDir {
279+
dir: TempDir,
280+
scenarios: HashSet<Scenario>,
281+
profile: Profile,
282+
backend: CodegenBackend,
283+
target: Target,
284+
}
285+
286+
// Materialize the test cases that we want to benchmark
287+
// We need to handle scenarios a bit specially, because they share the target directory
288+
let mut benchmark_dirs: Vec<BenchmarkDir> = vec![];
289+
278290
for backend in backends {
279291
for profile in &profiles {
280292
for target in targets {
281-
target_dirs.push((
282-
(*backend, *profile, *target),
283-
self.make_temp_dir(&self.path)?,
284-
));
293+
// Do we have any scenarios left to compute?
294+
let remaining_scenarios = scenarios
295+
.iter()
296+
.flat_map(|scenario| {
297+
self.create_test_cases(scenario, profile, backend, target)
298+
.into_iter()
299+
.map(|test_case| (*scenario, test_case))
300+
})
301+
.filter(|(_, test_case)| !already_computed.contains(test_case))
302+
.map(|(scenario, _)| scenario)
303+
.collect::<HashSet<Scenario>>();
304+
if remaining_scenarios.is_empty() {
305+
continue;
306+
}
307+
308+
let temp_dir = self.make_temp_dir(&self.path)?;
309+
benchmark_dirs.push(BenchmarkDir {
310+
dir: temp_dir,
311+
scenarios: remaining_scenarios,
312+
profile: *profile,
313+
backend: *backend,
314+
target: *target,
315+
});
285316
}
286317
}
287318
}
288319

320+
if benchmark_dirs.is_empty() {
321+
eprintln!(
322+
"Skipping {}: all test cases were previously computed",
323+
self.name
324+
);
325+
return Ok(());
326+
}
327+
328+
eprintln!(
329+
"Preparing {} (test cases: {})",
330+
self.name,
331+
benchmark_dirs.len()
332+
);
333+
289334
// In parallel (but with a limit to the number of CPUs), prepare all
290335
// profiles. This is done in parallel vs. sequentially because:
291336
// * We don't record any measurements during this phase, so the
@@ -319,18 +364,18 @@ impl Benchmark {
319364
.get(),
320365
)
321366
.context("jobserver::new")?;
322-
let mut threads = Vec::with_capacity(target_dirs.len());
323-
for ((backend, profile, target), prep_dir) in &target_dirs {
367+
let mut threads = Vec::with_capacity(benchmark_dirs.len());
368+
for benchmark_dir in &benchmark_dirs {
324369
let server = server.clone();
325370
let thread = s.spawn::<_, anyhow::Result<()>>(move || {
326371
wait_for_future(async move {
327372
let server = server.clone();
328373
self.mk_cargo_process(
329374
toolchain,
330-
prep_dir.path(),
331-
*profile,
332-
*backend,
333-
*target,
375+
benchmark_dir.dir.path(),
376+
benchmark_dir.profile,
377+
benchmark_dir.backend,
378+
benchmark_dir.target,
334379
)
335380
.jobserver(server)
336381
.run_rustc(false)
@@ -365,10 +410,11 @@ impl Benchmark {
365410
let mut timing_dirs: Vec<ManuallyDrop<TempDir>> = vec![];
366411

367412
let benchmark_start = std::time::Instant::now();
368-
for ((backend, profile, target), prep_dir) in &target_dirs {
369-
let backend = *backend;
370-
let profile = *profile;
371-
let target = *target;
413+
for benchmark_dir in &benchmark_dirs {
414+
let backend = benchmark_dir.backend;
415+
let profile = benchmark_dir.profile;
416+
let target = benchmark_dir.target;
417+
let scenarios = &benchmark_dir.scenarios;
372418
eprintln!(
373419
"Running {}: {:?} + {:?} + {:?} + {:?}",
374420
self.name, profile, scenarios, backend, target,
@@ -388,7 +434,7 @@ impl Benchmark {
388434
}
389435
log::debug!("Benchmark iteration {}/{}", i + 1, iterations);
390436
// Don't delete the directory on error.
391-
let timing_dir = ManuallyDrop::new(self.make_temp_dir(prep_dir.path())?);
437+
let timing_dir = ManuallyDrop::new(self.make_temp_dir(benchmark_dir.dir.path())?);
392438
let cwd = timing_dir.path();
393439

394440
// A full non-incremental build.
@@ -458,6 +504,42 @@ impl Benchmark {
458504

459505
Ok(())
460506
}
507+
508+
fn create_test_cases(
509+
&self,
510+
scenario: &Scenario,
511+
profile: &Profile,
512+
backend: &CodegenBackend,
513+
target: &Target,
514+
) -> Vec<CompileTestCase> {
515+
self.patches
516+
.iter()
517+
.map(|patch| CompileTestCase {
518+
benchmark: database::Benchmark::from(self.name.0.as_str()),
519+
profile: match profile {
520+
Profile::Check => database::Profile::Check,
521+
Profile::Debug => database::Profile::Debug,
522+
Profile::Doc => database::Profile::Doc,
523+
Profile::DocJson => database::Profile::DocJson,
524+
Profile::Opt => database::Profile::Opt,
525+
Profile::Clippy => database::Profile::Clippy,
526+
},
527+
scenario: match scenario {
528+
Scenario::Full => database::Scenario::Empty,
529+
Scenario::IncrFull => database::Scenario::IncrementalEmpty,
530+
Scenario::IncrUnchanged => database::Scenario::IncrementalFresh,
531+
Scenario::IncrPatched => database::Scenario::IncrementalPatch(patch.name),
532+
},
533+
backend: match backend {
534+
CodegenBackend::Llvm => database::CodegenBackend::Llvm,
535+
CodegenBackend::Cranelift => database::CodegenBackend::Cranelift,
536+
},
537+
target: match target {
538+
Target::X86_64UnknownLinuxGnu => database::Target::X86_64UnknownLinuxGnu,
539+
},
540+
})
541+
.collect()
542+
}
461543
}
462544

463545
/// Directory containing compile-time benchmarks.

0 commit comments

Comments
 (0)