aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
diff options
context:
space:
mode:
authorGravatar Eric Fellheimer <felly@google.com>2015-12-22 22:13:12 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2015-12-28 19:43:39 +0000
commit38816e7a10eb28b9bbdb217764e1b799c51ffb2f (patch)
tree683983b603e762a15ede305efe507dd9d47a5f55 /src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
parent19e19e2fba0e1185b89a2104517adcf1dfb8d4bd (diff)
Use batch lookups in graph-backed recursive provider for greater efficiency.
-- MOS_MIGRATED_REVID=110797095
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java135
1 files changed, 101 insertions, 34 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
index 051d05eceb..2768c31660 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/GraphBackedRecursivePackageProvider.java
@@ -13,9 +13,13 @@
// limitations under the License.
package com.google.devtools.build.lib.skyframe;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.PackageIdentifier.RepositoryName;
@@ -38,16 +42,19 @@ import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.WalkableGraph;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
- * A {@link RecursivePackageProvider} backed by a {@link WalkableGraph}, used by
- * {@code SkyQueryEnvironment} to look up the packages and targets matching the universe that's
- * been preloaded in {@code graph}.
- * */
+ * A {@link RecursivePackageProvider} backed by a {@link WalkableGraph}, used by {@code
+ * SkyQueryEnvironment} to look up the packages and targets matching the universe that's been
+ * preloaded in {@code graph}.
+ */
public final class GraphBackedRecursivePackageProvider implements RecursivePackageProvider {
private final WalkableGraph graph;
@@ -147,44 +154,76 @@ public final class GraphBackedRecursivePackageProvider implements RecursivePacka
ImmutableList.Builder<PathFragment> builder = ImmutableList.builder();
if (filteringPolicy != null) {
for (Path root : roots) {
- collectPackagesUnder(repository, RootedPath.toRootedPath(root, directory),
- excludedSubdirectories, builder, filteringPolicy);
+ RootedPath rootedDir = RootedPath.toRootedPath(root, directory);
+ TraversalInfo info = new TraversalInfo(rootedDir, excludedSubdirectories);
+ collectPackagesUnder(repository, ImmutableSet.of(info), builder, filteringPolicy);
}
}
return builder.build();
}
- private void collectPackagesUnder(RepositoryName repository, RootedPath directory,
- ImmutableSet<PathFragment> excludedSubdirectories,
- ImmutableList.Builder<PathFragment> builder, FilteringPolicy policy) {
- SkyKey key =
- PrepareDepsOfTargetsUnderDirectoryValue.key(
- repository, directory, excludedSubdirectories, policy);
- // If the key does not exist in the graph, because the SkyQuery environment has
- // already loaded the universe, and we found a TargetsBelowDirectory pattern in the universe
- // that contained it, then we know the directory does not exist in the universe.
- if (!graph.exists(key)) {
- return;
- }
+ private final void preloadPackages(final RepositoryName repositoryName,
+ Iterable<TraversalInfo> traversals) {
+ // Note that the return value is intentionally unused - we call this to elicit the side effect
+ // that the packages end up warm in the graph.
+ graph.getSuccessfulValues(Iterables.transform(traversals,
+ new Function<TraversalInfo, SkyKey>() {
+ @Override
+ public SkyKey apply(TraversalInfo traversalInfo) {
+ return PackageValue.key(
+ PackageIdentifier.create(repositoryName,
+ traversalInfo.rootedDir.getRelativePath()));
+ }
+ }));
+ }
- // If the key exists in the graph, then it must have a value and must not have an exception,
- // because PrepareDepsOfTargetsUnderDirectoryFunction#compute never throws.
- PrepareDepsOfTargetsUnderDirectoryValue prepDepsValue =
- (PrepareDepsOfTargetsUnderDirectoryValue) Preconditions.checkNotNull(graph.getValue(key));
- if (prepDepsValue.isDirectoryPackage()) {
- builder.add(directory.getRelativePath());
- }
- ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackages =
- prepDepsValue.getSubdirectoryTransitivelyContainsPackages();
- for (RootedPath subdirectory : subdirectoryTransitivelyContainsPackages.keySet()) {
- if (subdirectoryTransitivelyContainsPackages.get(subdirectory)) {
- PathFragment subdirectoryRelativePath = subdirectory.getRelativePath();
- ImmutableSet<PathFragment> excludedSubdirectoriesBeneathThisSubdirectory =
- PathFragment.filterPathsStartingWith(excludedSubdirectories, subdirectoryRelativePath);
- collectPackagesUnder(repository, subdirectory,
- excludedSubdirectoriesBeneathThisSubdirectory, builder, policy);
+ private void collectPackagesUnder(final RepositoryName repository,
+ Set<TraversalInfo> traversals, ImmutableList.Builder<PathFragment> builder,
+ final FilteringPolicy policy) {
+ Map<TraversalInfo, SkyKey> traversalToKeyMap =
+ Maps.asMap(traversals, new Function<TraversalInfo, SkyKey>() {
+ @Override
+ public SkyKey apply(TraversalInfo traversalInfo) {
+ return PrepareDepsOfTargetsUnderDirectoryValue.key(
+ repository, traversalInfo.rootedDir, traversalInfo.excludedSubdirectories, policy);
+ }
+ });
+ Map<SkyKey, SkyValue> values = graph.getSuccessfulValues(traversalToKeyMap.values());
+ // Preload the packages so subsequent lookups are faster. A better approach might be forego this
+ // here, and instead load the needed package in batch on demand.
+ preloadPackages(repository, traversals);
+
+ ImmutableSet.Builder<TraversalInfo> subdirTraversalBuilder = ImmutableSet.builder();
+ for (Map.Entry<TraversalInfo, SkyKey> entry : traversalToKeyMap.entrySet()) {
+ TraversalInfo info = entry.getKey();
+ SkyKey key = entry.getValue();
+ SkyValue val = values.get(key);
+ PrepareDepsOfTargetsUnderDirectoryValue prepDepsValue =
+ (PrepareDepsOfTargetsUnderDirectoryValue) val;
+ if (prepDepsValue != null) {
+ if (prepDepsValue.isDirectoryPackage()) {
+ builder.add(info.rootedDir.getRelativePath());
+ }
+
+ ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackages =
+ prepDepsValue.getSubdirectoryTransitivelyContainsPackages();
+ for (RootedPath subdirectory : subdirectoryTransitivelyContainsPackages.keySet()) {
+ if (subdirectoryTransitivelyContainsPackages.get(subdirectory)) {
+ PathFragment subdirectoryRelativePath = subdirectory.getRelativePath();
+ ImmutableSet<PathFragment> excludedSubdirectoriesBeneathThisSubdirectory =
+ PathFragment.filterPathsStartingWith(
+ info.excludedSubdirectories, subdirectoryRelativePath);
+ subdirTraversalBuilder.add(
+ new TraversalInfo(subdirectory, excludedSubdirectoriesBeneathThisSubdirectory));
+ }
+ }
}
}
+
+ ImmutableSet<TraversalInfo> subdirTraversals = subdirTraversalBuilder.build();
+ if (!subdirTraversals.isEmpty()) {
+ collectPackagesUnder(repository, subdirTraversals, builder, policy);
+ }
}
@Override
@@ -192,4 +231,32 @@ public final class GraphBackedRecursivePackageProvider implements RecursivePacka
throws NoSuchPackageException, NoSuchTargetException {
return getPackage(eventHandler, label.getPackageIdentifier()).getTarget(label.getName());
}
+
+ private static final class TraversalInfo {
+ private final RootedPath rootedDir;
+ private final ImmutableSet<PathFragment> excludedSubdirectories;
+
+ private TraversalInfo(RootedPath rootedDir, ImmutableSet<PathFragment> excludedSubdirectories) {
+ this.rootedDir = rootedDir;
+ this.excludedSubdirectories = excludedSubdirectories;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(rootedDir, excludedSubdirectories);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof TraversalInfo) {
+ TraversalInfo otherTraversal = (TraversalInfo) obj;
+ return Objects.equal(rootedDir, otherTraversal.rootedDir)
+ && Objects.equal(excludedSubdirectories, otherTraversal.excludedSubdirectories);
+ }
+ return false;
+ }
+ }
}