Skip to content

Commit 2f1ecf8

Browse files
committed
Filter compile-time test cases on a more granular level
1 parent b00da3e commit 2f1ecf8

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};
@@ -249,6 +250,7 @@ impl Benchmark {
249250
toolchain: &Toolchain,
250251
iterations: Option<usize>,
251252
targets: &[Target],
253+
already_computed: &hashbrown::HashSet<CompileTestCase>,
252254
) -> anyhow::Result<()> {
253255
if self.config.disabled {
254256
eprintln!("Skipping {}: disabled", self.name);
@@ -279,19 +281,62 @@ impl Benchmark {
279281
return Ok(());
280282
}
281283

282-
eprintln!("Preparing {}", self.name);
283-
let mut target_dirs: Vec<((CodegenBackend, Profile, Target), TempDir)> = vec![];
284+
struct BenchmarkDir {
285+
dir: TempDir,
286+
scenarios: HashSet<Scenario>,
287+
profile: Profile,
288+
backend: CodegenBackend,
289+
target: Target,
290+
}
291+
292+
// Materialize the test cases that we want to benchmark
293+
// We need to handle scenarios a bit specially, because they share the target directory
294+
let mut benchmark_dirs: Vec<BenchmarkDir> = vec![];
295+
284296
for backend in backends {
285297
for profile in &profiles {
286298
for target in targets {
287-
target_dirs.push((
288-
(*backend, *profile, *target),
289-
self.make_temp_dir(&self.path)?,
290-
));
299+
// Do we have any scenarios left to compute?
300+
let remaining_scenarios = scenarios
301+
.iter()
302+
.flat_map(|scenario| {
303+
self.create_test_cases(scenario, profile, backend, target)
304+
.into_iter()
305+
.map(|test_case| (*scenario, test_case))
306+
})
307+
.filter(|(_, test_case)| !already_computed.contains(test_case))
308+
.map(|(scenario, _)| scenario)
309+
.collect::<HashSet<Scenario>>();
310+
if remaining_scenarios.is_empty() {
311+
continue;
312+
}
313+
314+
let temp_dir = self.make_temp_dir(&self.path)?;
315+
benchmark_dirs.push(BenchmarkDir {
316+
dir: temp_dir,
317+
scenarios: remaining_scenarios,
318+
profile: *profile,
319+
backend: *backend,
320+
target: *target,
321+
});
291322
}
292323
}
293324
}
294325

326+
if benchmark_dirs.is_empty() {
327+
eprintln!(
328+
"Skipping {}: all test cases were previously computed",
329+
self.name
330+
);
331+
return Ok(());
332+
}
333+
334+
eprintln!(
335+
"Preparing {} (test cases: {})",
336+
self.name,
337+
benchmark_dirs.len()
338+
);
339+
295340
// In parallel (but with a limit to the number of CPUs), prepare all
296341
// profiles. This is done in parallel vs. sequentially because:
297342
// * We don't record any measurements during this phase, so the
@@ -325,18 +370,18 @@ impl Benchmark {
325370
.get(),
326371
)
327372
.context("jobserver::new")?;
328-
let mut threads = Vec::with_capacity(target_dirs.len());
329-
for ((backend, profile, target), prep_dir) in &target_dirs {
373+
let mut threads = Vec::with_capacity(benchmark_dirs.len());
374+
for benchmark_dir in &benchmark_dirs {
330375
let server = server.clone();
331376
let thread = s.spawn::<_, anyhow::Result<()>>(move || {
332377
wait_for_future(async move {
333378
let server = server.clone();
334379
self.mk_cargo_process(
335380
toolchain,
336-
prep_dir.path(),
337-
*profile,
338-
*backend,
339-
*target,
381+
benchmark_dir.dir.path(),
382+
benchmark_dir.profile,
383+
benchmark_dir.backend,
384+
benchmark_dir.target,
340385
)
341386
.jobserver(server)
342387
.run_rustc(false)
@@ -371,10 +416,11 @@ impl Benchmark {
371416
let mut timing_dirs: Vec<ManuallyDrop<TempDir>> = vec![];
372417

373418
let benchmark_start = std::time::Instant::now();
374-
for ((backend, profile, target), prep_dir) in &target_dirs {
375-
let backend = *backend;
376-
let profile = *profile;
377-
let target = *target;
419+
for benchmark_dir in &benchmark_dirs {
420+
let backend = benchmark_dir.backend;
421+
let profile = benchmark_dir.profile;
422+
let target = benchmark_dir.target;
423+
let scenarios = &benchmark_dir.scenarios;
378424
eprintln!(
379425
"Running {}: {:?} + {:?} + {:?} + {:?}",
380426
self.name, profile, scenarios, backend, target,
@@ -394,7 +440,7 @@ impl Benchmark {
394440
}
395441
log::debug!("Benchmark iteration {}/{}", i + 1, iterations);
396442
// Don't delete the directory on error.
397-
let timing_dir = ManuallyDrop::new(self.make_temp_dir(prep_dir.path())?);
443+
let timing_dir = ManuallyDrop::new(self.make_temp_dir(benchmark_dir.dir.path())?);
398444
let cwd = timing_dir.path();
399445

400446
// A full non-incremental build.
@@ -464,6 +510,42 @@ impl Benchmark {
464510

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

469551
/// Directory containing compile-time benchmarks.

0 commit comments

Comments
 (0)