Defer creating the full `PathFragment` for each dirent until we actually need it. This is a further optimization (after https://github.com/bazelbuild/bazel/commit/d7a9bb5b1e345097820a89fcda106dc7eb7d3fa0) for the same situation of a recursive glob that considers many dirents but few of which actually belong in the result. PiperOrigin-RevId: 625123534 Change-Id: I4d2334854dca1bb7b87c28adcdcabf65f0c5f85c
diff --git a/src/main/java/com/google/devtools/build/lib/packages/producers/FragmentProducer.java b/src/main/java/com/google/devtools/build/lib/packages/producers/FragmentProducer.java index 5618b34..acb433a 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/producers/FragmentProducer.java +++ b/src/main/java/com/google/devtools/build/lib/packages/producers/FragmentProducer.java
@@ -149,22 +149,14 @@ globDetail, base, fragmentIndex, resultSink, visitedGlobSubTasks); } - /** - * Attempts to add {@linkplain PathFragment the input file path} to {@linkplain ResultSink the - * result sink} if this is the last fragment in the glob expression and {@linkplain Operation glob - * operation} is {@link Operation#FILES} or {@link Operation#FILES_AND_DIRS}. - */ - static void maybeAddFileMatchingToResult( - PathFragment pathFragment, - int fragmentIndex, - GlobDetail globDetail, - FragmentProducer.ResultSink resultSink) { + /** Returns if a matching path at the given pattern index should be added to the result. */ + static boolean shouldAddFileMatchingToResult(int fragmentIndex, GlobDetail globDetail) { if (globDetail.globOperation().equals(Operation.SUBPACKAGES)) { - return; + return false; } if (fragmentIndex < globDetail.patternFragments().size() - 1) { - return; + return false; } - resultSink.acceptPathFragmentWithPackageFragment(pathFragment); + return true; } }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/producers/PatternWithWildcardProducer.java b/src/main/java/com/google/devtools/build/lib/packages/producers/PatternWithWildcardProducer.java index 2a8b283..d3594cb 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/producers/PatternWithWildcardProducer.java +++ b/src/main/java/com/google/devtools/build/lib/packages/producers/PatternWithWildcardProducer.java
@@ -105,20 +105,36 @@ if (dirent.getType() == Dirent.Type.UNKNOWN) { continue; } - if (!UnixGlob.matches(patternFragment, dirent.getName(), globDetail.regexPatternCache())) { + + String direntName = dirent.getName(); + + if (!UnixGlob.matches(patternFragment, direntName, globDetail.regexPatternCache())) { continue; } - // At this point, we know that the dirent matches current pattern fragment. - PathFragment child = base.getChild(dirent.getName()); + // At this point, we know that the dirent matches current pattern fragment but we don't yet + // know if it belongs in the result. Delay creating the full PathFragment until we actually + // need it. + if (dirent.getType() == Dirent.Type.SYMLINK) { tasks.enqueue( new SymlinkProducer( - FileValue.key(RootedPath.toRootedPath(globDetail.packageRoot(), child)), + FileValue.key( + RootedPath.toRootedPath(globDetail.packageRoot(), base.getChild(direntName))), (SymlinkProducer.ResultSink) this)); ++symlinksCount; + } else if (dirent.getType() == Dirent.Type.DIRECTORY) { + tasks.enqueue( + new DirectoryDirentProducer( + globDetail, + base.getChild(direntName), + fragmentIndex, + resultSink, + visitedGlobSubTasks)); } else { - handleDirent(child, dirent.getType() == Dirent.Type.DIRECTORY, tasks); + if (FragmentProducer.shouldAddFileMatchingToResult(fragmentIndex, globDetail)) { + resultSink.acceptPathFragmentWithPackageFragment(base.getChild(direntName)); + } } } @@ -179,9 +195,17 @@ return DONE; } - // When creating `DirentProducer` for symlinks, pass in the symlink path instead of the target - // path. - handleDirent(symlinkKey.argument().getRootRelativePath(), symlinkValue.isDirectory(), tasks); + // Use the symlink path instead of the target path. + PathFragment direntPath = symlinkKey.argument().getRootRelativePath(); + if (symlinkValue.isDirectory()) { + tasks.enqueue( + new DirectoryDirentProducer( + globDetail, direntPath, fragmentIndex, resultSink, visitedGlobSubTasks)); + } else { + if (FragmentProducer.shouldAddFileMatchingToResult(fragmentIndex, globDetail)) { + resultSink.acceptPathFragmentWithPackageFragment(direntPath); + } + } } // After all symlinks of dirents are processed, `symlinks` array list is useless and should be @@ -189,15 +213,4 @@ symlinks = null; return DONE; } - - private void handleDirent(PathFragment pathFragment, boolean isDir, Tasks tasks) { - if (isDir) { - tasks.enqueue( - new DirectoryDirentProducer( - globDetail, pathFragment, fragmentIndex, resultSink, visitedGlobSubTasks)); - } else { - FragmentProducer.maybeAddFileMatchingToResult( - pathFragment, fragmentIndex, globDetail, resultSink); - } - } }
diff --git a/src/main/java/com/google/devtools/build/lib/packages/producers/PatternWithoutWildcardProducer.java b/src/main/java/com/google/devtools/build/lib/packages/producers/PatternWithoutWildcardProducer.java index 4cf8a03..6a18f4a 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/producers/PatternWithoutWildcardProducer.java +++ b/src/main/java/com/google/devtools/build/lib/packages/producers/PatternWithoutWildcardProducer.java
@@ -91,7 +91,9 @@ return new DirectoryDirentProducer( globDetail, filePath, fragmentIndex, resultSink, visitedGlobSubTasks); } - FragmentProducer.maybeAddFileMatchingToResult(filePath, fragmentIndex, globDetail, resultSink); + if (FragmentProducer.shouldAddFileMatchingToResult(fragmentIndex, globDetail)) { + resultSink.acceptPathFragmentWithPackageFragment(filePath); + } return DONE; } }