diff options
| author | 2022-10-27 10:42:46 +0000 | |
|---|---|---|
| committer | 2022-10-28 07:15:55 +0000 | |
| commit | 6b236f1607e4a039700a287ff2368e02f583d6fd (patch) | |
| tree | 58660280516577c46a904768e5083fee92e84b7b | |
| parent | 4bb30b59a94ec5fc52712a6d86b29fa2eb77b6af (diff) | |
Multithread symlink forest removal.
This makes symlink forest creation ca. 2x faster again, taking 2-3
seconds instead of 5.
Who would have thought that os.RemoveAll() is slow.
Test: Presubmits.
Change-Id: I91e41319c972dbf1113cf723e383c785433c18b9
| -rw-r--r-- | bp2build/java_binary_host_conversion_test.go | 6 | ||||
| -rw-r--r-- | bp2build/symlink_forest.go | 43 |
2 files changed, 45 insertions, 4 deletions
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go index 86f3d423b..8000477b5 100644 --- a/bp2build/java_binary_host_conversion_test.go +++ b/bp2build/java_binary_host_conversion_test.go @@ -32,7 +32,7 @@ func runJavaBinaryHostTestCase(t *testing.T, tc Bp2buildTestCase) { }, tc) } -var fs = map[string]string{ +var testFs = map[string]string{ "test.mf": "Main-Class: com.android.test.MainClass", "other/Android.bp": `cc_library_host_shared { name: "jni-lib-1", @@ -43,7 +43,7 @@ var fs = map[string]string{ func TestJavaBinaryHost(t *testing.T) { runJavaBinaryHostTestCase(t, Bp2buildTestCase{ Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.", - Filesystem: fs, + Filesystem: testFs, Blueprint: `java_binary_host { name: "java-binary-host-1", srcs: ["a.java", "b.java"], @@ -76,7 +76,7 @@ func TestJavaBinaryHost(t *testing.T) { func TestJavaBinaryHostRuntimeDeps(t *testing.T) { runJavaBinaryHostTestCase(t, Bp2buildTestCase{ Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.", - Filesystem: fs, + Filesystem: testFs, Blueprint: `java_binary_host { name: "java-binary-host-1", static_libs: ["java-dep-1"], diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go index 45817e352..0fa9c5015 100644 --- a/bp2build/symlink_forest.go +++ b/bp2build/symlink_forest.go @@ -15,7 +15,9 @@ package bp2build import ( + "errors" "fmt" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -317,6 +319,45 @@ func plantSymlinkForestRecursive(context *symlinkForestContext, instructions *in } } +func removeParallelRecursive(path string, fi os.FileInfo, wg *sync.WaitGroup) { + defer wg.Done() + + if fi.IsDir() { + children := readdirToMap(path) + childrenWg := &sync.WaitGroup{} + childrenWg.Add(len(children)) + + for child, childFi := range children { + go removeParallelRecursive(shared.JoinPath(path, child), childFi, childrenWg) + } + + childrenWg.Wait() + } + + if err := os.Remove(path); err != nil { + fmt.Fprintf(os.Stderr, "Cannot unlink '%s': %s\n", path, err) + os.Exit(1) + } +} + +func removeParallel(path string) { + fi, err := os.Lstat(path) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return + } + + fmt.Fprintf(os.Stderr, "Cannot lstat '%s': %s\n", path, err) + os.Exit(1) + } + + wg := &sync.WaitGroup{} + wg.Add(1) + removeParallelRecursive(path, fi, wg) + + wg.Wait() +} + // Creates a symlink forest by merging the directory tree at "buildFiles" and // "srcDir" while excluding paths listed in "exclude". Returns the set of paths // under srcDir on which readdir() had to be called to produce the symlink @@ -330,7 +371,7 @@ func PlantSymlinkForest(verbose bool, topdir string, forest string, buildFiles s context.okay.Store(true) - os.RemoveAll(shared.JoinPath(topdir, forest)) + removeParallel(shared.JoinPath(topdir, forest)) instructions := instructionsFromExcludePathList(exclude) go func() { |