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;
}
}