diff options
author | 2016-07-18 20:33:28 +0000 | |
---|---|---|
committer | 2016-07-19 18:09:45 +0000 | |
commit | 063b4887b5ac2b1baaf5f6753abaa07736073831 (patch) | |
tree | 7729e435bd7e28970a48ad4aa159fcca04d1975d /src/main/java/com/google/devtools/build/lib/skyframe | |
parent | ee36dd3f5db8e7ad129b2782a24eb97a0478fc42 (diff) |
Sort the results returned by the HybridGlobber if we are using results from Skyframe globbing. This adds a log(n) factor to uses of globs, but getting globs to be returned in a reasonable order that can be emulated by legacy globbing is hard and bug-prone right now, and we must sort anyway if we are merging legacy and Skyframe globs.
Note that this log(n) factor is already present on clean builds with legacy globbing. If we end up seeing performance issues on incremental loading, we can investigate making GlobFunction efficiently return elements in sorted order. (We would still need to sort if merging legacy and Skyframe globs, but that should be a relatively rare occurrence, and can be dealt with by a more efficient merge sort if necessary.)
--
MOS_MIGRATED_REVID=127752554
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java | 3 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java | 27 |
2 files changed, 24 insertions, 6 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java index 5f8eaa90ea..cd4dd85f34 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java @@ -47,7 +47,8 @@ public final class GlobValue implements SkyValue { } /** - * Returns glob matches. + * Returns glob matches. The matches will be in a deterministic but unspecified order. If a + * particular order is required, the returned iterable should be sorted. */ public NestedSet<PathFragment> getMatches() { return matches; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java index 5d68e3f0dc..ad2f501612 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java @@ -68,6 +68,7 @@ import com.google.devtools.build.skyframe.ValueOrException4; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; @@ -1079,28 +1080,44 @@ public class PackageFunction implements SkyFunction { private List<String> resolve(Globber delegate) throws IOException, InterruptedException { LinkedHashSet<String> matches = Sets.newLinkedHashSet(); + // Skyframe globbing does not sort the list of results alphabetically, while legacy globbing + // does. To avoid non-deterministic sorting, we sort the result if it has any skyframe + // globs. We must also sort if merging legacy and Skyframe globs, since the end result + // should be deterministically ordered. + boolean needsSorting = false; for (SkyKey includeGlobKey : includesGlobKeys) { // TODO(bazel-team): NestedSet expansion here is suboptimal. for (PathFragment match : getGlobMatches(includeGlobKey, globValueMap)) { + needsSorting = true; matches.add(match.getPathString()); } } matches.addAll(delegate.fetch(delegateIncludesToken)); for (SkyKey excludeGlobKey : excludesGlobKeys) { for (PathFragment match : getGlobMatches(excludeGlobKey, globValueMap)) { + needsSorting = true; matches.remove(match.getPathString()); } } for (String delegateExcludeMatch : delegate.fetch(delegateExcludesToken)) { matches.remove(delegateExcludeMatch); } - return Lists.newArrayList(matches); + List<String> result = new ArrayList<>(matches); + if (needsSorting) { + Collections.sort(result); + } + return result; } - private Iterable<PathFragment> getGlobMatches(SkyKey globKey, - Map<SkyKey, ValueOrException4<IOException, BuildFileNotFoundException, - FileSymlinkCycleException, InconsistentFilesystemException>> globValueMap) - throws IOException { + private static Iterable<PathFragment> getGlobMatches( + SkyKey globKey, + Map< + SkyKey, + ValueOrException4< + IOException, BuildFileNotFoundException, FileSymlinkCycleException, + InconsistentFilesystemException>> + globValueMap) + throws IOException { ValueOrException4<IOException, BuildFileNotFoundException, FileSymlinkCycleException, InconsistentFilesystemException> valueOrException = Preconditions.checkNotNull(globValueMap.get(globKey), "%s should not be missing", |