From b048282c7893231d3a7191b251804973917b07a4 Mon Sep 17 00:00:00 2001 From: larsrc Date: Wed, 24 Feb 2021 08:58:34 -0800 Subject: [PATCH] Use readdir for cleanExisting in WorkerExecRoot. Consistently reduces system time spent under Linux, leaves the other metrics alone. May be even better under Mac, if it has a good implementation. RELNOTES: None. PiperOrigin-RevId: 359296744 --- .../build/lib/worker/WorkerExecRoot.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/worker/WorkerExecRoot.java b/src/main/java/com/google/devtools/build/lib/worker/WorkerExecRoot.java index 32f696f1928088..aa2417653edaa3 100644 --- a/src/main/java/com/google/devtools/build/lib/worker/WorkerExecRoot.java +++ b/src/main/java/com/google/devtools/build/lib/worker/WorkerExecRoot.java @@ -13,12 +13,15 @@ // limitations under the License. package com.google.devtools.build.lib.worker; +import static com.google.devtools.build.lib.vfs.Dirent.Type.DIRECTORY; +import static com.google.devtools.build.lib.vfs.Dirent.Type.SYMLINK; + import com.google.common.collect.Iterables; import com.google.devtools.build.lib.cmdline.LabelConstants; import com.google.devtools.build.lib.sandbox.SandboxHelpers; import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxInputs; import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxOutputs; -import com.google.devtools.build.lib.vfs.FileStatus; +import com.google.devtools.build.lib.vfs.Dirent; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; @@ -109,36 +112,38 @@ private void cleanExisting( Set dirsToCreate) throws IOException { Path execroot = workDir.getParentDirectory(); - for (Path path : root.getDirectoryEntries()) { - FileStatus stat = path.stat(Symlinks.NOFOLLOW); + for (Dirent dirent : root.readdir(Symlinks.NOFOLLOW)) { + Path absPath = root.getChild(dirent.getName()); PathFragment pathRelativeToWorkDir; - if (path.startsWith(workDir)) { + if (absPath.startsWith(workDir)) { // path is under workDir, i.e. execroot/. Simply get the relative path. - pathRelativeToWorkDir = path.relativeTo(workDir); + pathRelativeToWorkDir = absPath.relativeTo(workDir); } else { // path is not under workDir, which means it belongs to one of external repositories // symlinked directly under execroot. Get the relative path based on there and prepend it // with the designated prefix, '../', so that it's still a valid relative path to workDir. pathRelativeToWorkDir = - LabelConstants.EXPERIMENTAL_EXTERNAL_PATH_PREFIX.getRelative(path.relativeTo(execroot)); + LabelConstants.EXPERIMENTAL_EXTERNAL_PATH_PREFIX.getRelative( + absPath.relativeTo(execroot)); } Optional destination = getExpectedSymlinkDestination(pathRelativeToWorkDir, inputs); if (destination.isPresent()) { - if (stat.isSymbolicLink() && path.readSymbolicLink().equals(destination.get())) { + if (SYMLINK.equals(dirent.getType()) + && absPath.readSymbolicLink().equals(destination.get())) { inputsToCreate.remove(pathRelativeToWorkDir); } else { - path.delete(); + absPath.delete(); } - } else if (stat.isDirectory()) { + } else if (DIRECTORY.equals(dirent.getType())) { if (dirsToCreate.contains(pathRelativeToWorkDir)) { - cleanExisting(path, inputs, inputsToCreate, dirsToCreate); + cleanExisting(absPath, inputs, inputsToCreate, dirsToCreate); dirsToCreate.remove(pathRelativeToWorkDir); } else { - path.deleteTree(); + absPath.deleteTree(); } } else if (!inputsToCreate.contains(pathRelativeToWorkDir)) { - path.delete(); + absPath.delete(); } } }