Skip to content

Commit e0f9826

Browse files
committed
Create a separate prepared target directory for each codegen backend
1 parent b1a7f12 commit e0f9826

File tree

1 file changed

+73
-77
lines changed
  • collector/src/compile/benchmark

1 file changed

+73
-77
lines changed

collector/src/compile/benchmark/mod.rs

Lines changed: 73 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,12 @@ impl Benchmark {
263263
}
264264

265265
eprintln!("Preparing {}", self.name);
266-
let profile_dirs = profiles
267-
.iter()
268-
.map(|profile| Ok((*profile, self.make_temp_dir(&self.path)?)))
269-
.collect::<anyhow::Result<Vec<_>>>()?;
266+
let mut target_dirs: Vec<((CodegenBackend, Profile), TempDir)> = vec![];
267+
for backend in backends {
268+
for profile in &profiles {
269+
target_dirs.push(((*backend, *profile), self.make_temp_dir(&self.path)?));
270+
}
271+
}
270272

271273
// In parallel (but with a limit to the number of CPUs), prepare all
272274
// profiles. This is done in parallel vs. sequentially because:
@@ -290,22 +292,22 @@ impl Benchmark {
290292
// to do this in Cargo today. We would also ideally build in the same
291293
// target directory, but that's also not possible, as Cargo takes a
292294
// target-directory global lock during compilation.
295+
//
296+
// To avoid potential problems with recompilations, artifacts compiled by
297+
// different codegen backends are stored in separate directories.
293298
let preparation_start = std::time::Instant::now();
294299
std::thread::scope::<_, anyhow::Result<()>>(|s| {
295300
let server = jobserver::Client::new(num_cpus::get()).context("jobserver::new")?;
296-
let mut threads = Vec::with_capacity(profile_dirs.len());
297-
for (profile, prep_dir) in &profile_dirs {
301+
let mut threads = Vec::with_capacity(target_dirs.len());
302+
for ((backend, profile), prep_dir) in &target_dirs {
298303
let server = server.clone();
299304
let thread = s.spawn::<_, anyhow::Result<()>>(move || {
300305
wait_for_future(async move {
301-
// Prepare all backend artifacts into the same target directory
302-
for backend in backends {
303-
let server = server.clone();
304-
self.mk_cargo_process(toolchain, prep_dir.path(), *profile, *backend)
305-
.jobserver(server)
306-
.run_rustc(false)
307-
.await?;
308-
}
306+
let server = server.clone();
307+
self.mk_cargo_process(toolchain, prep_dir.path(), *profile, *backend)
308+
.jobserver(server)
309+
.run_rustc(false)
310+
.await?;
309311
Ok::<(), anyhow::Error>(())
310312
})?;
311313
Ok(())
@@ -331,88 +333,82 @@ impl Benchmark {
331333
);
332334

333335
let benchmark_start = std::time::Instant::now();
334-
for &backend in backends {
335-
for (profile, prep_dir) in &profile_dirs {
336-
let profile = *profile;
337-
eprintln!(
338-
"Running {}: {:?} + {:?} + {:?}",
339-
self.name, profile, scenarios, backend
340-
);
336+
for ((backend, profile), prep_dir) in &target_dirs {
337+
let backend = *backend;
338+
let profile = *profile;
339+
eprintln!(
340+
"Running {}: {:?} + {:?} + {:?}",
341+
self.name, profile, scenarios, backend
342+
);
343+
344+
// We want at least two runs for all benchmarks (since we run
345+
// self-profile separately).
346+
processor.start_first_collection();
347+
for i in 0..std::cmp::max(iterations, 2) {
348+
if i == 1 {
349+
let different = processor.finished_first_collection();
350+
if iterations == 1 && !different {
351+
// Don't run twice if this processor doesn't need it and
352+
// we've only been asked to run once.
353+
break;
354+
}
355+
}
356+
log::debug!("Benchmark iteration {}/{}", i + 1, iterations);
357+
// Don't delete the directory on error.
358+
let timing_dir = ManuallyDrop::new(self.make_temp_dir(prep_dir.path())?);
359+
let cwd = timing_dir.path();
360+
361+
// A full non-incremental build.
362+
if scenarios.contains(&Scenario::Full) {
363+
self.mk_cargo_process(toolchain, cwd, profile, backend)
364+
.processor(processor, Scenario::Full, "Full", None)
365+
.run_rustc(true)
366+
.await?;
367+
}
341368

342-
// We want at least two runs for all benchmarks (since we run
343-
// self-profile separately).
344-
processor.start_first_collection();
345-
for i in 0..std::cmp::max(iterations, 2) {
346-
if i == 1 {
347-
let different = processor.finished_first_collection();
348-
if iterations == 1 && !different {
349-
// Don't run twice if this processor doesn't need it and
350-
// we've only been asked to run once.
351-
break;
352-
}
369+
// Rustdoc does not support incremental compilation
370+
if profile != Profile::Doc {
371+
// An incremental from scratch (slowest incremental case).
372+
// This is required for any subsequent incremental builds.
373+
if scenarios.iter().any(|s| s.is_incr()) {
374+
self.mk_cargo_process(toolchain, cwd, profile, backend)
375+
.incremental(true)
376+
.processor(processor, Scenario::IncrFull, "IncrFull", None)
377+
.run_rustc(true)
378+
.await?;
353379
}
354-
log::debug!("Benchmark iteration {}/{}", i + 1, iterations);
355-
// Don't delete the directory on error.
356-
let timing_dir = ManuallyDrop::new(self.make_temp_dir(prep_dir.path())?);
357-
let cwd = timing_dir.path();
358380

359-
// A full non-incremental build.
360-
if scenarios.contains(&Scenario::Full) {
381+
// An incremental build with no changes (fastest incremental case).
382+
if scenarios.contains(&Scenario::IncrUnchanged) {
361383
self.mk_cargo_process(toolchain, cwd, profile, backend)
362-
.processor(processor, Scenario::Full, "Full", None)
384+
.incremental(true)
385+
.processor(processor, Scenario::IncrUnchanged, "IncrUnchanged", None)
363386
.run_rustc(true)
364387
.await?;
365388
}
366389

367-
// Rustdoc does not support incremental compilation
368-
if profile != Profile::Doc {
369-
// An incremental from scratch (slowest incremental case).
370-
// This is required for any subsequent incremental builds.
371-
if scenarios.iter().any(|s| s.is_incr()) {
372-
self.mk_cargo_process(toolchain, cwd, profile, backend)
373-
.incremental(true)
374-
.processor(processor, Scenario::IncrFull, "IncrFull", None)
375-
.run_rustc(true)
376-
.await?;
377-
}
390+
if scenarios.contains(&Scenario::IncrPatched) {
391+
for (i, patch) in self.patches.iter().enumerate() {
392+
log::debug!("applying patch {}", patch.name);
393+
patch.apply(cwd).map_err(|s| anyhow::anyhow!("{}", s))?;
378394

379-
// An incremental build with no changes (fastest incremental case).
380-
if scenarios.contains(&Scenario::IncrUnchanged) {
395+
// An incremental build with some changes (realistic
396+
// incremental case).
397+
let scenario_str = format!("IncrPatched{}", i);
381398
self.mk_cargo_process(toolchain, cwd, profile, backend)
382399
.incremental(true)
383400
.processor(
384401
processor,
385-
Scenario::IncrUnchanged,
386-
"IncrUnchanged",
387-
None,
402+
Scenario::IncrPatched,
403+
&scenario_str,
404+
Some(patch),
388405
)
389406
.run_rustc(true)
390407
.await?;
391408
}
392-
393-
if scenarios.contains(&Scenario::IncrPatched) {
394-
for (i, patch) in self.patches.iter().enumerate() {
395-
log::debug!("applying patch {}", patch.name);
396-
patch.apply(cwd).map_err(|s| anyhow::anyhow!("{}", s))?;
397-
398-
// An incremental build with some changes (realistic
399-
// incremental case).
400-
let scenario_str = format!("IncrPatched{}", i);
401-
self.mk_cargo_process(toolchain, cwd, profile, backend)
402-
.incremental(true)
403-
.processor(
404-
processor,
405-
Scenario::IncrPatched,
406-
&scenario_str,
407-
Some(patch),
408-
)
409-
.run_rustc(true)
410-
.await?;
411-
}
412-
}
413409
}
414-
drop(ManuallyDrop::into_inner(timing_dir));
415410
}
411+
drop(ManuallyDrop::into_inner(timing_dir));
416412
}
417413
}
418414
log::trace!(

0 commit comments

Comments
 (0)