Skip to content

Commit 9f98505

Browse files
committed
Calculate rustc outputs concurrently with other hashing tasks
Currently, `sccache` invokes `rustc` twice for generating the hash key: once for the inputs and env-deps (`--emit dep-info`), and another time for the output file names (`--print file-names`). However, the latter is invoked only after the former finishes. There is no reason for this dependency. Run `get_compiler_outputs` concurrently with the other `rustc` and hashing tasks in `RustHasher::generate_hash_key`. I initially thought that these two invocations could be merged together, but `--print` stop compilation before the `--emit` is evaluated, so I went with the simpler approach of just running them at the same time.
1 parent 1e2f32a commit 9f98505

File tree

1 file changed

+32
-25
lines changed

1 file changed

+32
-25
lines changed

src/compiler/rust.rs

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ static ALLOWED_EMIT: Lazy<HashSet<&'static str>> =
238238
/// Version number for cache key.
239239
const CACHE_VERSION: &[u8] = b"6";
240240

241-
/// Get absolute paths for all source files and env-deps listed in rustc's dep-info output.
241+
/// Run `rustc --emit=dep-info` to get the list of source files and env-deps.
242242
async fn get_source_files_and_env_deps<T>(
243243
creator: &T,
244244
crate_name: &str,
@@ -382,22 +382,25 @@ async fn get_compiler_outputs<T>(
382382
where
383383
T: Clone + CommandCreatorSync,
384384
{
385+
let start = time::Instant::now();
385386
let mut cmd = creator.clone().new_command_sync(executable);
386387
cmd.args(&arguments)
387388
.args(&["--print", "file-names"])
388389
.env_clear()
389390
.envs(env_vars.to_vec())
390391
.current_dir(cwd);
391-
if log_enabled!(Trace) {
392-
trace!("get_compiler_outputs: {:?}", cmd);
393-
}
392+
trace!("get_compiler_outputs: {:?}", cmd);
394393
let outputs = run_input_output(cmd, None).await?;
395394

396395
let outstr = String::from_utf8(outputs.stdout).context("Error parsing rustc output")?;
397-
if log_enabled!(Trace) {
398-
trace!("get_compiler_outputs: {:?}", outstr);
399-
}
400-
Ok(outstr.lines().map(|l| l.to_owned()).collect())
396+
let outputs = outstr.lines().map(|l| l.to_owned()).collect::<Vec<_>>();
397+
trace!(
398+
"get_compiler_outputs: got {} outputs in {}: {:?}",
399+
outputs.len(),
400+
fmt_duration_as_secs(&start.elapsed()),
401+
outstr,
402+
);
403+
Ok(outputs)
401404
}
402405

403406
impl Rust {
@@ -1382,6 +1385,23 @@ where
13821385
Ok((source_files, source_hashes, env_deps))
13831386
};
13841387

1388+
// Turn arguments into a simple Vec<OsString> to calculate outputs.
1389+
let flat_os_string_arguments: Vec<OsString> = os_string_arguments
1390+
.iter()
1391+
.cloned()
1392+
.flat_map(|(arg, val)| iter::once(arg).chain(val))
1393+
.collect();
1394+
let outputs = async {
1395+
get_compiler_outputs(
1396+
creator,
1397+
&self.executable,
1398+
flat_os_string_arguments,
1399+
&cwd,
1400+
&env_vars,
1401+
)
1402+
.await
1403+
};
1404+
13851405
// Hash the contents of the externs listed on the commandline.
13861406
trace!(
13871407
"[{}]: hashing {} externs",
@@ -1423,17 +1443,19 @@ where
14231443

14241444
let target_json_hash = hash_all(&target_json_files, pool);
14251445

1426-
// Perform all hashing operations on the files.
1446+
// Invoke the compiler and perform all hashing operations on the files.
14271447
let (
14281448
(source_files, source_hashes, mut env_deps),
14291449
extern_hashes,
14301450
staticlib_hashes,
14311451
target_json_hash,
1452+
mut outputs,
14321453
) = futures::try_join!(
14331454
source_files_and_hashes_and_env_deps,
14341455
extern_hashes,
14351456
staticlib_hashes,
1436-
target_json_hash
1457+
target_json_hash,
1458+
outputs,
14371459
)?;
14381460

14391461
// If you change any of the inputs to the hash, you should change `CACHE_VERSION`.
@@ -1539,21 +1561,6 @@ where
15391561
// 10. The version of the compiler.
15401562
self.version.hash(&mut HashToDigest { digest: &mut m });
15411563

1542-
// Turn arguments into a simple Vec<OsString> to calculate outputs.
1543-
let flat_os_string_arguments: Vec<OsString> = os_string_arguments
1544-
.into_iter()
1545-
.flat_map(|(arg, val)| iter::once(arg).chain(val))
1546-
.collect();
1547-
1548-
let mut outputs = get_compiler_outputs(
1549-
creator,
1550-
&self.executable,
1551-
flat_os_string_arguments,
1552-
&cwd,
1553-
&env_vars,
1554-
)
1555-
.await?;
1556-
15571564
// metadata / dep-info don't ever generate binaries, but
15581565
// rustc still makes them appear in the --print
15591566
// file-names output (see

0 commit comments

Comments
 (0)