Skip to content

Commit 9d72651

Browse files
authored
Rollup merge of #145460 - Kobzol:bootstrap-speedup-copy-src-dirs, r=jieyouxu
Speedup `copy_src_dirs` in bootstrap I was kinda offended by how slow it was. Just the `copy_src_dirs` part took ~3s locally in the `x dist rustc-src` step. In release mode it was just 1s, but that's kind of cheating (I wonder if we should build bootstrap in release mode on CI though...). Did some basic optimizations to bring it down to ~1s also in debug mode. Maybe it's overkill, due to #145455. Up to you whether we should merge it or close it :) r? `````````@jieyouxu`````````
2 parents 3b396fc + cdea62d commit 9d72651

File tree

2 files changed

+42
-40
lines changed

2 files changed

+42
-40
lines changed

src/bootstrap/src/core/build_steps/dist.rs

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -916,79 +916,74 @@ fn copy_src_dirs(
916916
exclude_dirs: &[&str],
917917
dst_dir: &Path,
918918
) {
919+
// The src directories should be relative to `base`, we depend on them not being absolute
920+
// paths below.
921+
for src_dir in src_dirs {
922+
assert!(Path::new(src_dir).is_relative());
923+
}
924+
919925
// Iterating, filtering and copying a large number of directories can be quite slow.
920926
// Avoid doing it in dry run (and thus also tests).
921927
if builder.config.dry_run() {
922928
return;
923929
}
924930

925931
fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
932+
// The paths are relative, e.g. `llvm-project/...`.
926933
let spath = match path.to_str() {
927934
Some(path) => path,
928935
None => return false,
929936
};
930937
if spath.ends_with('~') || spath.ends_with(".pyc") {
931938
return false;
932939
}
940+
// Normalize slashes
941+
let spath = spath.replace("\\", "/");
933942

934-
const LLVM_PROJECTS: &[&str] = &[
943+
static LLVM_PROJECTS: &[&str] = &[
935944
"llvm-project/clang",
936-
"llvm-project\\clang",
937945
"llvm-project/libunwind",
938-
"llvm-project\\libunwind",
939946
"llvm-project/lld",
940-
"llvm-project\\lld",
941947
"llvm-project/lldb",
942-
"llvm-project\\lldb",
943948
"llvm-project/llvm",
944-
"llvm-project\\llvm",
945949
"llvm-project/compiler-rt",
946-
"llvm-project\\compiler-rt",
947950
"llvm-project/cmake",
948-
"llvm-project\\cmake",
949951
"llvm-project/runtimes",
950-
"llvm-project\\runtimes",
951952
"llvm-project/third-party",
952-
"llvm-project\\third-party",
953953
];
954-
if spath.contains("llvm-project")
955-
&& !spath.ends_with("llvm-project")
956-
&& !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
957-
{
958-
return false;
959-
}
954+
if spath.starts_with("llvm-project") && spath != "llvm-project" {
955+
if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
956+
return false;
957+
}
960958

961-
// Keep only these third party libraries
962-
const LLVM_THIRD_PARTY: &[&str] =
963-
&["llvm-project/third-party/siphash", "llvm-project\\third-party\\siphash"];
964-
if (spath.starts_with("llvm-project/third-party")
965-
|| spath.starts_with("llvm-project\\third-party"))
966-
&& !(spath.ends_with("llvm-project/third-party")
967-
|| spath.ends_with("llvm-project\\third-party"))
968-
&& !LLVM_THIRD_PARTY.iter().any(|path| spath.contains(path))
969-
{
970-
return false;
971-
}
959+
// Keep siphash third-party dependency
960+
if spath.starts_with("llvm-project/third-party")
961+
&& spath != "llvm-project/third-party"
962+
&& !spath.starts_with("llvm-project/third-party/siphash")
963+
{
964+
return false;
965+
}
972966

973-
const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
974-
if LLVM_TEST.iter().any(|path| spath.contains(path))
975-
&& (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
976-
{
977-
return false;
967+
if spath.starts_with("llvm-project/llvm/test")
968+
&& (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
969+
{
970+
return false;
971+
}
978972
}
979973

980974
// Cargo tests use some files like `.gitignore` that we would otherwise exclude.
981-
const CARGO_TESTS: &[&str] = &["tools/cargo/tests", "tools\\cargo\\tests"];
982-
if CARGO_TESTS.iter().any(|path| spath.contains(path)) {
975+
if spath.starts_with("tools/cargo/tests") {
983976
return true;
984977
}
985978

986-
let full_path = Path::new(dir).join(path);
987-
if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
988-
return false;
979+
if !exclude_dirs.is_empty() {
980+
let full_path = Path::new(dir).join(path);
981+
if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
982+
return false;
983+
}
989984
}
990985

991-
let excludes = [
986+
static EXCLUDES: &[&str] = &[
992987
"CVS",
993988
"RCS",
994989
"SCCS",
@@ -1011,7 +1006,15 @@ fn copy_src_dirs(
10111006
".hgrags",
10121007
"_darcs",
10131008
];
1014-
!path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
1009+
1010+
// We want to check if any component of `path` doesn't contain the strings in `EXCLUDES`.
1011+
// However, since we traverse directories top-down in `Builder::cp_link_filtered`,
1012+
// it is enough to always check only the last component:
1013+
// - If the path is a file, we will iterate to it and then check it's filename
1014+
// - If the path is a dir, if it's dir name contains an excluded string, we will not even
1015+
// recurse into it.
1016+
let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1017+
!EXCLUDES.contains(&last_component)
10151018
}
10161019

10171020
// Copy the directories using our filter

src/bootstrap/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1862,7 +1862,6 @@ impl Build {
18621862
self.create_dir(&dst);
18631863
self.cp_link_filtered_recurse(&path, &dst, &relative, filter);
18641864
} else {
1865-
let _ = fs::remove_file(&dst);
18661865
self.copy_link(&path, &dst, FileType::Regular);
18671866
}
18681867
}

0 commit comments

Comments
 (0)