Skip to content

Commit fe431ec

Browse files
Merge pull request #738 from Mark-Simulacrum/share-build-cache
Share target directories between benchmarks
2 parents a22b1b2 + 2781848 commit fe431ec

File tree

2 files changed

+66
-31
lines changed

2 files changed

+66
-31
lines changed

collector/src/execute.rs

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ impl Profiler {
198198

199199
struct CargoProcess<'a> {
200200
compiler: Compiler<'a>,
201-
cwd: &'a Path,
201+
src_dir: &'a Path,
202+
target_directory: &'a Path,
202203
build_kind: BuildKind,
203204
incremental: bool,
204205
processor_etc: Option<(&'a mut dyn Processor, RunKind, &'a str, Option<&'a Patch>)>,
@@ -227,7 +228,7 @@ impl<'a> CargoProcess<'a> {
227228
self
228229
}
229230

230-
fn base_command(&self, cwd: &Path, subcommand: &str) -> Command {
231+
fn base_command(&self, subcommand: &str) -> Command {
231232
let mut cmd = Command::new(Path::new(self.compiler.cargo));
232233
cmd
233234
// Not all cargo invocations (e.g. `cargo clean`) need all of these
@@ -239,7 +240,7 @@ impl<'a> CargoProcess<'a> {
239240
// and any in-tree dependencies, and we don't want that; it wastes
240241
// time.
241242
.env("CARGO_INCREMENTAL", "0")
242-
.current_dir(cwd)
243+
.current_dir(self.src_dir)
243244
.arg(subcommand)
244245
.arg("--manifest-path")
245246
.arg(&self.manifest_path);
@@ -250,10 +251,10 @@ impl<'a> CargoProcess<'a> {
250251
cmd
251252
}
252253

253-
fn get_pkgid(&self, cwd: &Path) -> anyhow::Result<String> {
254-
let mut pkgid_cmd = self.base_command(cwd, "pkgid");
254+
fn get_pkgid(&self) -> anyhow::Result<String> {
255+
let mut pkgid_cmd = self.base_command("pkgid");
255256
let out = command_output(&mut pkgid_cmd)
256-
.with_context(|| format!("failed to obtain pkgid in '{:?}'", cwd))?
257+
.with_context(|| format!("failed to obtain pkgid in '{:?}'", self.src_dir))?
257258
.stdout;
258259
let package_id = str::from_utf8(&out).unwrap();
259260
Ok(package_id.trim().to_string())
@@ -305,8 +306,8 @@ impl<'a> CargoProcess<'a> {
305306
}
306307
};
307308

308-
let mut cmd = self.base_command(self.cwd, subcommand);
309-
cmd.arg("-p").arg(self.get_pkgid(self.cwd)?);
309+
let mut cmd = self.base_command(subcommand);
310+
cmd.arg("-p").arg(self.get_pkgid()?);
310311
match self.build_kind {
311312
BuildKind::Check => {
312313
cmd.arg("--profile").arg("check");
@@ -322,6 +323,8 @@ impl<'a> CargoProcess<'a> {
322323
cmd.arg("-Zunstable-options");
323324
cmd.arg("-Ztimings");
324325
}
326+
// --target-dir is not universally read, but this hopefully is.
327+
cmd.env("CARGO_TARGET_DIR", self.target_directory);
325328
cmd.arg("--");
326329
// --wrap-rustc-with is not a valid rustc flag. But rustc-fake
327330
// recognizes it, strips it (and its argument) out, and uses it as an
@@ -353,10 +356,10 @@ impl<'a> CargoProcess<'a> {
353356
// in-tree (e.g., in the case of the servo crates there are a lot of
354357
// other components).
355358
if let Some(file) = &self.touch_file {
356-
touch(&self.cwd, Path::new(&file))?;
359+
touch(&self.src_dir, Path::new(&file))?;
357360
} else {
358361
touch_all(
359-
&self.cwd.join(
362+
&self.src_dir.join(
360363
Path::new(&self.manifest_path)
361364
.parent()
362365
.expect("manifest has parent"),
@@ -374,7 +377,7 @@ impl<'a> CargoProcess<'a> {
374377
if self.incremental {
375378
cmd.arg("-C");
376379
let mut incr_arg = std::ffi::OsString::from("incremental=");
377-
incr_arg.push(self.cwd.join("incremental-state"));
380+
incr_arg.push(self.target_directory.join("incremental-state"));
378381
cmd.arg(incr_arg);
379382
}
380383

@@ -388,7 +391,7 @@ impl<'a> CargoProcess<'a> {
388391
if let Some((ref mut processor, run_kind, run_kind_str, patch)) = self.processor_etc {
389392
let data = ProcessOutputData {
390393
name: self.processor_name.clone(),
391-
cwd: self.cwd,
394+
cwd: self.src_dir,
392395
build_kind: self.build_kind,
393396
run_kind,
394397
run_kind_str,
@@ -952,7 +955,8 @@ impl Benchmark {
952955
fn mk_cargo_process<'a>(
953956
&'a self,
954957
compiler: Compiler<'a>,
955-
cwd: &'a Path,
958+
target_directory: &'a Path,
959+
src_dir: &'a Path,
956960
build_kind: BuildKind,
957961
) -> CargoProcess<'a> {
958962
let mut cargo_args = self
@@ -973,7 +977,8 @@ impl Benchmark {
973977
CargoProcess {
974978
compiler,
975979
processor_name: self.name.clone(),
976-
cwd,
980+
target_directory,
981+
src_dir,
977982
build_kind,
978983
incremental: false,
979984
processor_etc: None,
@@ -1000,22 +1005,24 @@ impl Benchmark {
10001005
pub fn measure(
10011006
&self,
10021007
processor: &mut dyn Processor,
1003-
build_kinds: &[BuildKind],
1008+
build_kinds_and_target_dir: &[(BuildKind, &Path)],
10041009
run_kinds: &[RunKind],
10051010
compiler: Compiler<'_>,
10061011
iterations: usize,
10071012
) -> anyhow::Result<()> {
10081013
let iterations = cmp::min(iterations, self.config.runs);
10091014

1010-
if self.config.disabled || build_kinds.is_empty() {
1015+
if self.config.disabled || build_kinds_and_target_dir.is_empty() {
10111016
eprintln!("Skipping {}: disabled", self.name);
10121017
bail!("disabled benchmark");
10131018
}
10141019

10151020
eprintln!("Preparing {}", self.name);
1016-
let build_kind_dirs = build_kinds
1021+
1022+
// These directories are *target* directories.
1023+
let build_kind_dirs = build_kinds_and_target_dir
10171024
.iter()
1018-
.map(|kind| Ok((*kind, self.make_temp_dir(&self.path)?)))
1025+
.map(|(kind, target_dir)| Ok((*kind, target_dir, self.make_temp_dir(&self.path)?)))
10191026
.collect::<anyhow::Result<Vec<_>>>()?;
10201027

10211028
// In parallel (but with a limit to the number of CPUs), prepare all
@@ -1041,10 +1048,10 @@ impl Benchmark {
10411048
// target-directory global lock during compilation.
10421049
crossbeam_utils::thread::scope::<_, anyhow::Result<()>>(|s| {
10431050
let server = jobserver::Client::new(num_cpus::get()).context("jobserver::new")?;
1044-
for (build_kind, prep_dir) in &build_kind_dirs {
1051+
for (build_kind, target_dir, src_dir) in &build_kind_dirs {
10451052
let server = server.clone();
10461053
s.spawn::<_, anyhow::Result<()>>(move |_| {
1047-
self.mk_cargo_process(compiler, prep_dir.path(), *build_kind)
1054+
self.mk_cargo_process(compiler, target_dir, src_dir.path(), *build_kind)
10481055
.jobserver(server)
10491056
.run_rustc(false)?;
10501057
Ok(())
@@ -1054,7 +1061,7 @@ impl Benchmark {
10541061
})
10551062
.unwrap()?;
10561063

1057-
for (build_kind, prep_dir) in build_kind_dirs {
1064+
for (build_kind, target_dir, src_dir) in build_kind_dirs {
10581065
eprintln!("Running {}: {:?} + {:?}", self.name, build_kind, run_kinds);
10591066

10601067
// We want at least two runs for all benchmarks (since we run
@@ -1070,12 +1077,14 @@ impl Benchmark {
10701077
}
10711078
}
10721079
log::debug!("Benchmark iteration {}/{}", i + 1, iterations);
1073-
let timing_dir = self.make_temp_dir(prep_dir.path())?;
1074-
let cwd = timing_dir.path();
1080+
let target_dir = self.make_temp_dir(target_dir)?;
1081+
let target_dir = target_dir.path();
1082+
let src_dir = self.make_temp_dir(src_dir.path())?;
1083+
let src_dir = src_dir.path();
10751084

10761085
// A full non-incremental build.
10771086
if run_kinds.contains(&RunKind::Full) {
1078-
self.mk_cargo_process(compiler, cwd, build_kind)
1087+
self.mk_cargo_process(compiler, target_dir, src_dir, build_kind)
10791088
.processor(processor, RunKind::Full, "Full", None)
10801089
.run_rustc(true)?;
10811090
}
@@ -1088,15 +1097,15 @@ impl Benchmark {
10881097
|| run_kinds.contains(&RunKind::IncrUnchanged)
10891098
|| run_kinds.contains(&RunKind::IncrPatched)
10901099
{
1091-
self.mk_cargo_process(compiler, cwd, build_kind)
1100+
self.mk_cargo_process(compiler, target_dir, src_dir, build_kind)
10921101
.incremental(true)
10931102
.processor(processor, RunKind::IncrFull, "IncrFull", None)
10941103
.run_rustc(true)?;
10951104
}
10961105

10971106
// An incremental build with no changes (fastest incremental case).
10981107
if run_kinds.contains(&RunKind::IncrUnchanged) {
1099-
self.mk_cargo_process(compiler, cwd, build_kind)
1108+
self.mk_cargo_process(compiler, target_dir, src_dir, build_kind)
11001109
.incremental(true)
11011110
.processor(processor, RunKind::IncrUnchanged, "IncrUnchanged", None)
11021111
.run_rustc(true)?;
@@ -1105,12 +1114,12 @@ impl Benchmark {
11051114
if run_kinds.contains(&RunKind::IncrPatched) {
11061115
for (i, patch) in self.patches.iter().enumerate() {
11071116
log::debug!("applying patch {}", patch.name);
1108-
patch.apply(cwd).map_err(|s| anyhow::anyhow!("{}", s))?;
1117+
patch.apply(src_dir).map_err(|s| anyhow::anyhow!("{}", s))?;
11091118

11101119
// An incremental build with some changes (realistic
11111120
// incremental case).
11121121
let run_kind_str = format!("IncrPatched{}", i);
1113-
self.mk_cargo_process(compiler, cwd, build_kind)
1122+
self.mk_cargo_process(compiler, target_dir, src_dir, build_kind)
11141123
.incremental(true)
11151124
.processor(
11161125
processor,

collector/src/main.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::path::{Path, PathBuf};
1313
use std::process;
1414
use std::process::Command;
1515
use std::{str, time::Instant};
16+
use tempfile::TempDir;
1617
use tokio::runtime::Runtime;
1718

1819
mod execute;
@@ -207,6 +208,16 @@ fn bench(
207208
);
208209
}
209210

211+
let bk_and_targets = build_kinds
212+
.iter()
213+
.map(|kind| Ok((*kind, TempDir::new()?)))
214+
.collect::<anyhow::Result<Vec<_>>>()
215+
.expect("created temp directories");
216+
let bk_and_targets = bk_and_targets
217+
.iter()
218+
.map(|(k, td)| (*k, td.path()))
219+
.collect::<Vec<_>>();
220+
210221
let steps = benchmarks
211222
.iter()
212223
.map(|b| b.name.to_string())
@@ -250,8 +261,13 @@ fn bench(
250261
interned_cid,
251262
self_profile,
252263
);
253-
let result =
254-
benchmark.measure(&mut processor, build_kinds, run_kinds, compiler, iterations);
264+
let result = benchmark.measure(
265+
&mut processor,
266+
&bk_and_targets,
267+
run_kinds,
268+
compiler,
269+
iterations,
270+
);
255271
if let Err(s) = result {
256272
eprintln!(
257273
"collector error: Failed to benchmark '{}', recorded: {}",
@@ -734,12 +750,22 @@ fn main_result() -> anyhow::Result<i32> {
734750

735751
eprintln!("Profiling with {:?}", profiler);
736752

753+
let bk_and_targets = build_kinds
754+
.iter()
755+
.map(|kind| Ok((*kind, TempDir::new()?)))
756+
.collect::<anyhow::Result<Vec<_>>>()
757+
.expect("created temp directories");
758+
let bk_and_targets = bk_and_targets
759+
.iter()
760+
.map(|(k, td)| (*k, td.path()))
761+
.collect::<Vec<_>>();
762+
737763
let mut errors = BenchmarkErrors::new();
738764
for (i, benchmark) in benchmarks.iter().enumerate() {
739765
eprintln!("{}", n_benchmarks_remaining(benchmarks.len() - i));
740766
let mut processor = execute::ProfileProcessor::new(profiler, &out_dir, &id);
741767
let result =
742-
benchmark.measure(&mut processor, &build_kinds, &run_kinds, compiler, 1);
768+
benchmark.measure(&mut processor, &bk_and_targets, &run_kinds, compiler, 1);
743769
if let Err(ref s) = result {
744770
errors.incr();
745771
eprintln!(

0 commit comments

Comments
 (0)