Refactor the ActionLookupValue/ConfiguredObjectValue hierarchy to reflect the reality that some configured targets will never have associated actions (all non-rule configured targets, including input/output files, aliases, and package groups).
This allows us to more explicitly track the different categories of configured targets for metrics. Because non-rule configured targets can depend on rule configured targets (an output file depends on its generating rule, an alias depends on a target), the traversal of the analysis graph that powers these metrics must still visit these non-rule configured targets, allowing them to be tracked with little additional overhead.
As a small optimization, we can delete from the Skyframe graph any nodes corresponding to non-rule configured targets if dropping the analysis phase.
PiperOrigin-RevId: 368457602
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionLookupKey.java b/src/main/java/com/google/devtools/build/lib/actions/ActionLookupKey.java
index 62db95b..fa81239 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionLookupKey.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionLookupKey.java
@@ -16,7 +16,12 @@
import com.google.devtools.build.skyframe.SkyKey;
/**
- * {@link SkyKey} for an {@link ActionLookupValue}.
+ * {@link SkyKey} for an "analysis object": either an {@link ActionLookupValue} or a {@link
+ * com.google.devtools.build.lib.analysis.ConfiguredTargetValue}.
+ *
+ * <p>Whether a configured target creates actions cannot be inferred from its {@link
+ * com.google.devtools.build.lib.cmdline.Label} without performing analysis, so this class is used
+ * for both types. Non-{@link ActionLookupValue} nodes are not accessed during the execution phase.
*
* <p>All subclasses of {@link ActionLookupValue} "own" artifacts with {@link ArtifactOwner}s that
* are subclasses of {@link ActionLookupKey}. This allows callers to easily find the value key,
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionLookupValue.java b/src/main/java/com/google/devtools/build/lib/actions/ActionLookupValue.java
index 6dbc68a..ef536c8 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionLookupValue.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionLookupValue.java
@@ -14,9 +14,7 @@
package com.google.devtools.build.lib.actions;
import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.actions.Artifact.SourceArtifact;
import com.google.devtools.build.skyframe.SkyValue;
-import javax.annotation.Nullable;
/** Base interface for all values which can provide the generating action of an artifact. */
public interface ActionLookupValue extends SkyValue {
@@ -52,11 +50,4 @@
default int getNumActions() {
return getActions().size();
}
-
- /** Returns a source artifact if the underlying configured target is an input file. */
- @Nullable
- default SourceArtifact getSourceArtifact() {
- return null;
- }
-
}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/AnalysisGraphStatsEvent.java b/src/main/java/com/google/devtools/build/lib/actions/AnalysisGraphStatsEvent.java
index 45a4039..4d6b82b 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/AnalysisGraphStatsEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/AnalysisGraphStatsEvent.java
@@ -13,34 +13,22 @@
// limitations under the License.
package com.google.devtools.build.lib.actions;
+import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
+
/**
* Event transporting data about the size/shape of the analysis graph. Only emitted when Bazel is
* forced to visit the entire analysis graph (for action/artifact conflict checking). See {@link
* com.google.devtools.build.lib.skyframe.SkyframeBuildView#shouldCheckForConflicts}.
*/
public final class AnalysisGraphStatsEvent {
- private final TotalAndConfiguredTargetOnlyMetric actionLookupValueCount;
- private final TotalAndConfiguredTargetOnlyMetric actionCount;
- private final int outputArtifactCount;
+ private final BuildEventStreamProtos.BuildMetrics.BuildGraphMetrics buildGraphMetrics;
public AnalysisGraphStatsEvent(
- TotalAndConfiguredTargetOnlyMetric actionLookupValueCount,
- TotalAndConfiguredTargetOnlyMetric actionCount,
- int outputArtifactCount) {
- this.actionLookupValueCount = actionLookupValueCount;
- this.actionCount = actionCount;
- this.outputArtifactCount = outputArtifactCount;
+ BuildEventStreamProtos.BuildMetrics.BuildGraphMetrics buildGraphMetrics) {
+ this.buildGraphMetrics = buildGraphMetrics;
}
- public TotalAndConfiguredTargetOnlyMetric getActionLookupValueCount() {
- return actionLookupValueCount;
- }
-
- public TotalAndConfiguredTargetOnlyMetric getActionCount() {
- return actionCount;
- }
-
- public int getOutputArtifactCount() {
- return outputArtifactCount;
+ public BuildEventStreamProtos.BuildMetrics.BuildGraphMetrics getBuildGraphMetrics() {
+ return buildGraphMetrics;
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/actions/BUILD b/src/main/java/com/google/devtools/build/lib/actions/BUILD
index 9e9551d..153b81e 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/actions/BUILD
@@ -155,7 +155,7 @@
java_library(
name = "analysis_graph_stats_event",
srcs = ["AnalysisGraphStatsEvent.java"],
- deps = [":total_and_configured_target_only_metric"],
+ deps = ["//src/main/java/com/google/devtools/build/lib/buildeventstream/proto:build_event_stream_java_proto"],
)
java_library(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AspectValue.java b/src/main/java/com/google/devtools/build/lib/analysis/AspectValue.java
index 58a84d0..0c18c7f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AspectValue.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectValue.java
@@ -24,7 +24,7 @@
import net.starlark.java.syntax.Location;
/** An aspect in the context of the Skyframe graph. */
-public final class AspectValue extends BasicActionLookupValue implements ConfiguredObjectValue {
+public final class AspectValue extends BasicActionLookupValue implements RuleConfiguredObjectValue {
// These variables are only non-final because they may be clear()ed to save memory. They are null
// only after they are cleared except for transitivePackagesForPackageRootResolution.
@Nullable private Aspect aspect;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BUILD b/src/main/java/com/google/devtools/build/lib/analysis/BUILD
index 4a3d8c1..e41e289 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BUILD
@@ -313,7 +313,6 @@
":config/transitions/split_transition",
":config/transitions/transition_factory",
":configurations_collector",
- ":configured_object_value",
":configured_target",
":constraints/constraint_constants",
":constraints/constraint_semantics",
@@ -341,6 +340,7 @@
":provider_collection",
":required_config_fragments_provider",
":resolved_toolchain_context",
+ ":rule_configured_object_value",
":rule_definition_context",
":rule_definition_environment",
":starlark/args",
@@ -689,7 +689,6 @@
srcs = ["ConfiguredObjectValue.java"],
deps = [
":provider_collection",
- "//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/collect/nestedset",
"//src/main/java/com/google/devtools/build/lib/packages",
"//src/main/java/com/google/devtools/build/skyframe",
@@ -697,12 +696,20 @@
)
java_library(
+ name = "rule_configured_object_value",
+ srcs = ["RuleConfiguredObjectValue.java"],
+ deps = [
+ ":configured_object_value",
+ "//src/main/java/com/google/devtools/build/lib/actions",
+ ],
+)
+
+java_library(
name = "configured_target",
srcs = ["ConfiguredTarget.java"],
deps = [
":config/config_matching_provider",
":transitive_info_collection",
- "//src/main/java/com/google/devtools/build/lib/actions:artifacts",
"//src/main/java/com/google/devtools/build/lib/cmdline",
"//src/main/java/com/google/devtools/build/lib/skyframe:build_configuration_value",
"//src/main/java/net/starlark/java/eval",
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredObjectValue.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredObjectValue.java
index 353cbd5..b06000a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredObjectValue.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredObjectValue.java
@@ -13,13 +13,15 @@
// limitations under the License.
package com.google.devtools.build.lib.analysis;
-import com.google.devtools.build.lib.actions.ActionLookupValue;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.skyframe.NotComparableSkyValue;
-/** Super-interface for {@link ConfiguredTargetValue} and {@link AspectValue}. */
-public interface ConfiguredObjectValue extends ActionLookupValue, NotComparableSkyValue {
+/**
+ * Super-interface for {@link ConfiguredTargetValue} and {@link RuleConfiguredObjectValue}
+ * (transitively including {@link AspectValue}).
+ */
+public interface ConfiguredObjectValue extends NotComparableSkyValue {
/** Returns the configured target/aspect for this value. */
ProviderCollection getConfiguredObject();
@@ -34,11 +36,10 @@
NestedSet<Package> getTransitivePackagesForPackageRootResolution();
/**
- * Clears provider data from this value, leaving only the artifact->generating action map.
+ * Clears data from this value.
*
* <p>Should only be used when user specifies --discard_analysis_cache. Must be called at most
- * once per value, after which {@link #getConfiguredObject} and {@link #getActions} cannot be
- * called.
+ * once per value, after which this object's other methods cannot be called.
*/
void clear(boolean clearEverything);
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
index 4404f56..735276c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTarget.java
@@ -16,7 +16,6 @@
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.actions.Artifact.SourceArtifact;
import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
@@ -71,12 +70,6 @@
@Override
Object getValue(String name);
- /** Returns a source artifact if this is an input file. */
- @Nullable
- default SourceArtifact getSourceArtifact() {
- return null;
- }
-
/**
* If the configured target is an alias, return the actual target, otherwise return the current
* target. This follows alias chains.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredObjectValue.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredObjectValue.java
new file mode 100644
index 0000000..74e1333
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredObjectValue.java
@@ -0,0 +1,23 @@
+// Copyright 2021 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.analysis;
+
+import com.google.devtools.build.lib.actions.ActionLookupValue;
+
+/**
+ * Common interface for {@link AspectValue} and {@link
+ * com.google.devtools.build.lib.skyframe.RuleConfiguredTargetValue}
+ */
+public interface RuleConfiguredObjectValue extends ConfiguredObjectValue, ActionLookupValue {}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/InputFileConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/InputFileConfiguredTarget.java
index d980d27..e397337 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/InputFileConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/InputFileConfiguredTarget.java
@@ -101,7 +101,6 @@
printer.append("<input file target " + getLabel() + ">");
}
- @Override
public SourceArtifact getSourceArtifact() {
return artifact;
}
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto b/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
index 75c6b78..21c93a6 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
+++ b/src/main/java/com/google/devtools/build/lib/buildeventstream/proto/build_event_stream.proto
@@ -865,11 +865,14 @@
message BuildGraphMetrics {
// How many configured targets/aspects were in this build, including any
// that were analyzed on a prior build and are still valid. May not be
- // populated if analysis phase was fully cached.
+ // populated if analysis phase was fully cached. Note: for historical
+ // reasons this includes input/output files and other configured targets
+ // that do not actually have associated actions.
int32 action_lookup_value_count = 1;
// How many configured targets alone were in this build: always at most
// action_lookup_value_count. Useful mainly for historical comparisons to
- // TargetMetrics.targets_configured, which used to not count aspects.
+ // TargetMetrics.targets_configured, which used to not count aspects. This
+ // also includes configured targets that do not have associated actions.
int32 action_lookup_value_count_not_including_aspects = 5;
// How many actions belonged to the configured targets/aspects above. It may
// not be necessary to execute all of these actions to build the requested
@@ -879,6 +882,15 @@
// action_count. Useful mainly for historical comparisons to
// ActionMetrics.actions_created, which used to not count aspects' actions.
int32 action_count_not_including_aspects = 6;
+ // How many "input file" configured targets there were: one per source file.
+ // Should agree with artifact_metrics.source_artifacts_read.count above,
+ int32 input_file_configured_target_count = 7;
+ // How many "output file" configured targets there were: output files that
+ // are targets (not implicit outputs).
+ int32 output_file_configured_target_count = 8;
+ // How many "other" configured targets there were (like alias,
+ // package_group, and other non-rule non-file configured targets).
+ int32 other_configured_target_count = 9;
// How many artifacts are outputs of the above actions. May not be populated
// if analysis phase was fully cached.
int32 output_artifact_count = 3;
diff --git a/src/main/java/com/google/devtools/build/lib/metrics/BUILD b/src/main/java/com/google/devtools/build/lib/metrics/BUILD
index 45af86c..dcb1be5 100644
--- a/src/main/java/com/google/devtools/build/lib/metrics/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/metrics/BUILD
@@ -37,6 +37,7 @@
"//src/main/java/com/google/devtools/build/lib/actions:analysis_graph_stats_event",
"//src/main/java/com/google/devtools/build/lib/analysis:analysis_phase_complete_event",
"//src/main/java/com/google/devtools/build/lib/analysis:analysis_phase_started_event",
+ "//src/main/java/com/google/devtools/build/lib/bugreport",
"//src/main/java/com/google/devtools/build/lib/buildeventstream/proto:build_event_stream_java_proto",
"//src/main/java/com/google/devtools/build/lib/profiler",
"//src/main/java/com/google/devtools/build/lib/skyframe:execution_finished_event",
diff --git a/src/main/java/com/google/devtools/build/lib/metrics/MetricsCollector.java b/src/main/java/com/google/devtools/build/lib/metrics/MetricsCollector.java
index 18d2b2d..4666d56 100644
--- a/src/main/java/com/google/devtools/build/lib/metrics/MetricsCollector.java
+++ b/src/main/java/com/google/devtools/build/lib/metrics/MetricsCollector.java
@@ -20,6 +20,7 @@
import com.google.devtools.build.lib.actions.TotalAndConfiguredTargetOnlyMetric;
import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
import com.google.devtools.build.lib.analysis.AnalysisPhaseStartedEvent;
+import com.google.devtools.build.lib.bugreport.BugReport;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics.ActionSummary;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics.ArtifactMetrics;
@@ -100,15 +101,16 @@
@SuppressWarnings("unused")
@Subscribe
public synchronized void logAnalysisGraphStats(AnalysisGraphStatsEvent event) {
- TotalAndConfiguredTargetOnlyMetric actionLookupValueCount = event.getActionLookupValueCount();
- TotalAndConfiguredTargetOnlyMetric actionCount = event.getActionCount();
- buildGraphMetrics
- .setActionLookupValueCount(actionLookupValueCount.total())
- .setActionLookupValueCountNotIncludingAspects(
- actionLookupValueCount.configuredTargetsOnly())
- .setActionCount(actionCount.total())
- .setActionCountNotIncludingAspects(actionCount.configuredTargetsOnly())
- .setOutputArtifactCount(event.getOutputArtifactCount());
+ // Check only one event per build. No proto3 check for presence, so check for not-default value.
+ if (buildGraphMetrics.getActionLookupValueCount() > 0) {
+ BugReport.sendBugReport(
+ new IllegalStateException(
+ "Already initialized build graph metrics builder: "
+ + buildGraphMetrics
+ + ", "
+ + event.getBuildGraphMetrics()));
+ }
+ buildGraphMetrics.mergeFrom(event.getBuildGraphMetrics());
}
@SuppressWarnings("unused")
diff --git a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphProtoOutputFormatterCallback.java b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphProtoOutputFormatterCallback.java
index 945a240..e29e5b2 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphProtoOutputFormatterCallback.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphProtoOutputFormatterCallback.java
@@ -16,9 +16,9 @@
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
import com.google.devtools.build.lib.analysis.AspectValue;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
-import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.TargetAccessor;
+import com.google.devtools.build.lib.skyframe.RuleConfiguredTargetValue;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.skyframe.actiongraph.v2.ActionGraphDump;
import com.google.devtools.build.lib.skyframe.actiongraph.v2.AqueryOutputHandler;
@@ -92,12 +92,15 @@
options.includeCommandline |= options.includeParamFiles;
for (ConfiguredTargetValue configuredTargetValue : partialResult) {
- actionGraphDump.dumpConfiguredTarget(configuredTargetValue);
+ if (!(configuredTargetValue instanceof RuleConfiguredTargetValue)) {
+ // We have to include non-rule values in the graph to visit their dependencies, but they
+ // don't have any actions to print out.
+ continue;
+ }
+ actionGraphDump.dumpConfiguredTarget((RuleConfiguredTargetValue) configuredTargetValue);
if (options.useAspects) {
- if (configuredTargetValue.getConfiguredTarget() instanceof RuleConfiguredTarget) {
- for (AspectValue aspectValue : accessor.getAspectValues(configuredTargetValue)) {
- actionGraphDump.dumpAspect(aspectValue, configuredTargetValue);
- }
+ for (AspectValue aspectValue : accessor.getAspectValues(configuredTargetValue)) {
+ actionGraphDump.dumpAspect(aspectValue, configuredTargetValue);
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java
index fccabc4..29ac05c 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/aquery/ActionGraphTextOutputFormatterCallback.java
@@ -29,12 +29,12 @@
import com.google.devtools.build.lib.analysis.AspectValue;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
-import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.buildeventstream.BuildEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.TargetAccessor;
+import com.google.devtools.build.lib.skyframe.RuleConfiguredTargetValue;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.util.CommandDescriptionForm;
import com.google.devtools.build.lib.util.CommandFailureUtils;
@@ -79,15 +79,19 @@
options.includeCommandline |= options.includeParamFiles;
for (ConfiguredTargetValue configuredTargetValue : partialResult) {
- for (ActionAnalysisMetadata action : configuredTargetValue.getActions()) {
+ if (!(configuredTargetValue instanceof RuleConfiguredTargetValue)) {
+ // We have to include non-rule values in the graph to visit their dependencies, but they
+ // don't have any actions to print out.
+ continue;
+ }
+ for (ActionAnalysisMetadata action :
+ ((RuleConfiguredTargetValue) configuredTargetValue).getActions()) {
writeAction(action, printStream);
}
if (options.useAspects) {
- if (configuredTargetValue.getConfiguredTarget() instanceof RuleConfiguredTarget) {
- for (AspectValue aspectValue : accessor.getAspectValues(configuredTargetValue)) {
- for (ActionAnalysisMetadata action : aspectValue.getActions()) {
- writeAction(action, printStream);
- }
+ for (AspectValue aspectValue : accessor.getAspectValues(configuredTargetValue)) {
+ for (ActionAnalysisMetadata action : aspectValue.getActions()) {
+ writeAction(action, printStream);
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactConflictFinder.java b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactConflictFinder.java
index 8eb9a8f..611eae5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactConflictFinder.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ArtifactConflictFinder.java
@@ -23,19 +23,15 @@
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionLookupValue;
import com.google.devtools.build.lib.actions.Actions;
-import com.google.devtools.build.lib.actions.AnalysisGraphStatsEvent;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactPrefixConflictException;
import com.google.devtools.build.lib.actions.MapBasedActionGraph;
import com.google.devtools.build.lib.actions.MutableActionGraph;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
-import com.google.devtools.build.lib.actions.TotalAndConfiguredTargetOnlyMetric;
-import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.concurrent.ExecutorUtil;
import com.google.devtools.build.lib.concurrent.Sharder;
import com.google.devtools.build.lib.concurrent.ThrowableRecordingRunnableWrapper;
import com.google.devtools.build.lib.skyframe.PrecomputedValue.Precomputed;
-import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.List;
import java.util.Map;
@@ -50,6 +46,8 @@
class ArtifactConflictFinder {
static final Precomputed<ImmutableMap<ActionAnalysisMetadata, ConflictException>>
ACTION_CONFLICTS = new Precomputed<>("action_conflicts");
+ // Action graph construction is CPU-bound.
+ static final int NUM_JOBS = Runtime.getRuntime().availableProcessors();
private ArtifactConflictFinder() {}
@@ -65,7 +63,7 @@
* build as of 2014), so it should only be called when necessary.
*/
static ActionConflictsAndStats findAndStoreArtifactConflicts(
- Iterable<ActionLookupValue> actionLookupValues,
+ Sharder<ActionLookupValue> actionLookupValues,
boolean strictConflictChecks,
ActionKeyContext actionKeyContext)
throws InterruptedException {
@@ -74,9 +72,8 @@
MapBasedActionGraph actionGraph = new MapBasedActionGraph(actionKeyContext);
ConcurrentNavigableMap<PathFragment, Artifact> artifactPathMap =
new ConcurrentSkipListMap<>(Actions.comparatorForPrefixConflicts());
- Pair<TotalAndConfiguredTargetOnlyMetric, TotalAndConfiguredTargetOnlyMetric> counts =
- constructActionGraphAndPathMap(
- actionGraph, artifactPathMap, actionLookupValues, temporaryBadActionMap);
+ constructActionGraphAndPathMap(
+ actionGraph, artifactPathMap, actionLookupValues, temporaryBadActionMap);
Map<ActionAnalysisMetadata, ArtifactPrefixConflictException> actionsWithArtifactPrefixConflict =
Actions.findArtifactPrefixConflicts(actionGraph, artifactPathMap, strictConflictChecks);
@@ -87,8 +84,6 @@
}
return ActionConflictsAndStats.create(
ImmutableMap.copyOf(temporaryBadActionMap),
- counts.first,
- counts.second,
actionGraph.getSize());
}
@@ -97,53 +92,33 @@
* PathFragment}s to their respective {@link Artifact}s. We do this in a threadpool to save around
* 1.5 seconds on a mid-sized build versus a single-threaded operation.
*/
- private static Pair<TotalAndConfiguredTargetOnlyMetric, TotalAndConfiguredTargetOnlyMetric>
- constructActionGraphAndPathMap(
- MutableActionGraph actionGraph,
- ConcurrentNavigableMap<PathFragment, Artifact> artifactPathMap,
- Iterable<ActionLookupValue> values,
- ConcurrentMap<ActionAnalysisMetadata, ConflictException> badActionMap)
- throws InterruptedException {
- // Action graph construction is CPU-bound.
- int numJobs = Runtime.getRuntime().availableProcessors();
- // No great reason for expecting 5000 action lookup values, but not worth counting size of
- // values.
- Sharder<ActionLookupValue> actionShards = new Sharder<>(numJobs, 5000);
- int actionLookupValueCount = 0;
- int configuredTargetValueCount = 0;
- int actionCount = 0;
- int configuredTargetActionCount = 0;
- for (ActionLookupValue value : values) {
- actionShards.add(value);
- actionLookupValueCount++;
- actionCount += value.getNumActions();
- if (value instanceof ConfiguredTargetValue) {
- configuredTargetValueCount++;
- configuredTargetActionCount += value.getNumActions();
- }
- }
-
+ private static void constructActionGraphAndPathMap(
+ MutableActionGraph actionGraph,
+ ConcurrentNavigableMap<PathFragment, Artifact> artifactPathMap,
+ Sharder<ActionLookupValue> actionShards,
+ ConcurrentMap<ActionAnalysisMetadata, ConflictException> badActionMap)
+ throws InterruptedException {
ThrowableRecordingRunnableWrapper wrapper =
new ThrowableRecordingRunnableWrapper(
"ArtifactConflictFinder#constructActionGraphAndPathMap");
ExecutorService executor =
Executors.newFixedThreadPool(
- numJobs,
+ NUM_JOBS,
new ThreadFactoryBuilder().setNameFormat("ActionLookupValue Processor %d").build());
for (List<ActionLookupValue> shard : actionShards) {
executor.execute(
wrapper.wrap(actionRegistration(shard, actionGraph, artifactPathMap, badActionMap)));
}
boolean interrupted = ExecutorUtil.interruptibleShutdown(executor);
- Throwables.propagateIfPossible(wrapper.getFirstThrownError());
+ Throwable firstThrownError = wrapper.getFirstThrownError();
+ if (firstThrownError != null) {
+ Throwables.throwIfUnchecked(firstThrownError);
+ throw new IllegalStateException(firstThrownError);
+ }
if (interrupted) {
throw new InterruptedException();
}
- return Pair.of(
- TotalAndConfiguredTargetOnlyMetric.create(
- actionLookupValueCount, configuredTargetValueCount),
- TotalAndConfiguredTargetOnlyMetric.create(actionCount, configuredTargetActionCount));
}
private static Runnable actionRegistration(
@@ -215,15 +190,12 @@
abstract static class ActionConflictsAndStats {
abstract ImmutableMap<ActionAnalysisMetadata, ConflictException> getConflicts();
- abstract AnalysisGraphStatsEvent getStats();
+ abstract int getOutputArtifactCount();
private static ActionConflictsAndStats create(
ImmutableMap<ActionAnalysisMetadata, ConflictException> conflicts,
- TotalAndConfiguredTargetOnlyMetric actionValueCount,
- TotalAndConfiguredTargetOnlyMetric actionCount,
int artifactCount) {
- return new AutoValue_ArtifactConflictFinder_ActionConflictsAndStats(
- conflicts, new AnalysisGraphStatsEvent(actionValueCount, actionCount, artifactCount));
+ return new AutoValue_ArtifactConflictFinder_ActionConflictsAndStats(conflicts, artifactCount);
}
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
index 2f7a38d..6ff4409 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BUILD
@@ -219,6 +219,7 @@
"//src/main/java/com/google/devtools/build/lib:keep-going-option",
"//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/actions:action_lookup_key",
+ "//src/main/java/com/google/devtools/build/lib/actions:analysis_graph_stats_event",
"//src/main/java/com/google/devtools/build/lib/actions:artifacts",
"//src/main/java/com/google/devtools/build/lib/actions:commandline_item",
"//src/main/java/com/google/devtools/build/lib/actions:file_metadata",
@@ -255,6 +256,7 @@
"//src/main/java/com/google/devtools/build/lib/analysis:platform_configuration",
"//src/main/java/com/google/devtools/build/lib/analysis:platform_options",
"//src/main/java/com/google/devtools/build/lib/analysis:resolved_toolchain_context",
+ "//src/main/java/com/google/devtools/build/lib/analysis:rule_configured_object_value",
"//src/main/java/com/google/devtools/build/lib/analysis:toolchain_collection",
"//src/main/java/com/google/devtools/build/lib/analysis:toolchain_context",
"//src/main/java/com/google/devtools/build/lib/analysis:top_level_artifact_context",
@@ -760,11 +762,8 @@
deps = [
":precomputed_value",
"//src/main/java/com/google/devtools/build/lib/actions",
- "//src/main/java/com/google/devtools/build/lib/actions:analysis_graph_stats_event",
"//src/main/java/com/google/devtools/build/lib/actions:artifacts",
- "//src/main/java/com/google/devtools/build/lib/analysis:configured_target_value",
"//src/main/java/com/google/devtools/build/lib/concurrent",
- "//src/main/java/com/google/devtools/build/lib/util",
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
"//third_party:auto_value",
"//third_party:guava",
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
index e33b6a9..950693a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -22,8 +22,6 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.flogger.GoogleLogger;
-import com.google.devtools.build.lib.actions.Actions;
-import com.google.devtools.build.lib.actions.Actions.GeneratingActions;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.AnalysisRootCauseEvent;
import com.google.devtools.build.lib.analysis.AspectResolver;
@@ -242,7 +240,6 @@
// not prepared for it.
return new NonRuleConfiguredTargetValue(
new EmptyConfiguredTarget(target.getLabel(), configuredTargetKey.getConfigurationKey()),
- GeneratingActions.EMPTY,
transitivePackagesForPackageRootResolution == null
? null
: transitivePackagesForPackageRootResolution.build());
@@ -1059,22 +1056,14 @@
? null
: transitivePackagesForPackageRootResolution.build());
} else {
- GeneratingActions generatingActions;
- // Check for conflicting actions within this configured target (that indicates a bug in the
- // rule implementation).
- try {
- generatingActions =
- Actions.assignOwnersAndFilterSharedActionsAndThrowActionConflict(
- analysisEnvironment.getActionKeyContext(),
- analysisEnvironment.getRegisteredActions(),
- configuredTargetKey,
- /*outputFiles=*/ null);
- } catch (ActionConflictException e) {
- throw new ConfiguredTargetFunctionException(e);
- }
+ Preconditions.checkState(
+ analysisEnvironment.getRegisteredActions().isEmpty(),
+ "Non-rule can't have actions: %s %s %s %s",
+ configuredTargetKey,
+ analysisEnvironment.getRegisteredActions(),
+ configuredTarget);
return new NonRuleConfiguredTargetValue(
configuredTarget,
- generatingActions,
transitivePackagesForPackageRootResolution == null
? null
: transitivePackagesForPackageRootResolution.build());
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/NonRuleConfiguredTargetValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/NonRuleConfiguredTargetValue.java
index 3826ef9..e1c96d2 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/NonRuleConfiguredTargetValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/NonRuleConfiguredTargetValue.java
@@ -13,13 +13,8 @@
// limitations under the License.
package com.google.devtools.build.lib.skyframe;
-import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
-import com.google.devtools.build.lib.actions.Actions.GeneratingActions;
-import com.google.devtools.build.lib.actions.Artifact.SourceArtifact;
-import com.google.devtools.build.lib.actions.BasicActionLookupValue;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
@@ -36,10 +31,7 @@
@ThreadSafe
// Reached via OutputFileConfiguredTarget.
@AutoCodec(explicitlyAllowClass = RuleConfiguredTarget.class)
-@VisibleForTesting
-public final class NonRuleConfiguredTargetValue extends BasicActionLookupValue
- implements ConfiguredTargetValue {
-
+public final class NonRuleConfiguredTargetValue implements ConfiguredTargetValue {
// These variables are only non-final because they may be clear()ed to save memory.
// configuredTarget is null only after it is cleared.
@Nullable private ConfiguredTarget configuredTarget;
@@ -50,20 +42,15 @@
@AutoCodec.Instantiator
@VisibleForSerialization
NonRuleConfiguredTargetValue(
- ImmutableList<ActionAnalysisMetadata> actions,
ConfiguredTarget configuredTarget) {
- super(actions);
- this.configuredTarget = configuredTarget;
// Transitive packages are not serialized.
- this.transitivePackagesForPackageRootResolution = null;
+ this(configuredTarget, null);
}
NonRuleConfiguredTargetValue(
ConfiguredTarget configuredTarget,
- GeneratingActions generatingActions,
@Nullable NestedSet<Package> transitivePackagesForPackageRootResolution) {
- super(generatingActions);
- this.configuredTarget = Preconditions.checkNotNull(configuredTarget, generatingActions);
+ this.configuredTarget = Preconditions.checkNotNull(configuredTarget);
this.transitivePackagesForPackageRootResolution = transitivePackagesForPackageRootResolution;
}
@@ -74,12 +61,6 @@
}
@Override
- public ImmutableList<ActionAnalysisMetadata> getActions() {
- Preconditions.checkNotNull(configuredTarget, this);
- return actions;
- }
-
- @Override
public NestedSet<Package> getTransitivePackagesForPackageRootResolution() {
return Preconditions.checkNotNull(transitivePackagesForPackageRootResolution);
}
@@ -95,11 +76,6 @@
@Override
public String toString() {
- return getStringHelper().add("configuredTarget", configuredTarget).toString();
- }
-
- @Override
- public SourceArtifact getSourceArtifact() {
- return configuredTarget == null ? null : configuredTarget.getSourceArtifact();
+ return MoreObjects.toStringHelper(this).add("configuredTarget", configuredTarget).toString();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RuleConfiguredTargetValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/RuleConfiguredTargetValue.java
index e94b49f..a1ca50c 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RuleConfiguredTargetValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RuleConfiguredTargetValue.java
@@ -17,9 +17,9 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
-import com.google.devtools.build.lib.actions.ActionLookupValue;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ConfiguredTargetValue;
+import com.google.devtools.build.lib.analysis.RuleConfiguredObjectValue;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
@@ -32,7 +32,8 @@
@Immutable
@ThreadSafe
@AutoCodec(explicitlyAllowClass = RuleConfiguredTarget.class)
-public final class RuleConfiguredTargetValue implements ActionLookupValue, ConfiguredTargetValue {
+public final class RuleConfiguredTargetValue
+ implements RuleConfiguredObjectValue, ConfiguredTargetValue {
// This variable is non-final because it may be clear()ed to save memory. It is null only after
// clear(true) is called.
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
index 8e29c08..9e9638b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java
@@ -762,8 +762,8 @@
SkyValue value = skyKeyAndValue.getValue();
SkyKey key = skyKeyAndValue.getKey();
SkyFunctionName functionName = key.functionName();
- if (functionName.equals(SkyFunctions.CONFIGURED_TARGET)) {
- ConfiguredTargetValue ctValue = (ConfiguredTargetValue) value;
+ if (value instanceof RuleConfiguredTargetValue) {
+ RuleConfiguredTargetValue ctValue = (RuleConfiguredTargetValue) value;
ConfiguredTarget configuredTarget = ctValue.getConfiguredTarget();
if (configuredTarget instanceof RuleConfiguredTarget) {
@@ -808,20 +808,20 @@
memoizingEvaluator.getDoneValues().entrySet()) {
SkyKey key = skyKeyAndValue.getKey();
SkyValue skyValue = skyKeyAndValue.getValue();
- SkyFunctionName functionName = key.functionName();
- try {
+ if (skyValue == null) {
// The skyValue may be null in case analysis of the previous build failed.
- if (skyValue != null) {
- if (functionName.equals(SkyFunctions.CONFIGURED_TARGET)) {
- actionGraphDump.dumpConfiguredTarget((ConfiguredTargetValue) skyValue);
- } else if (functionName.equals(SkyFunctions.ASPECT)) {
- AspectValue aspectValue = (AspectValue) skyValue;
- AspectKey aspectKey = (AspectKey) key;
- ConfiguredTargetValue configuredTargetValue =
- (ConfiguredTargetValue)
- memoizingEvaluator.getExistingValue(aspectKey.getBaseConfiguredTargetKey());
- actionGraphDump.dumpAspect(aspectValue, configuredTargetValue);
- }
+ continue;
+ }
+ try {
+ if (skyValue instanceof RuleConfiguredTargetValue) {
+ actionGraphDump.dumpConfiguredTarget((RuleConfiguredTargetValue) skyValue);
+ } else if (key.functionName().equals(SkyFunctions.ASPECT)) {
+ AspectValue aspectValue = (AspectValue) skyValue;
+ AspectKey aspectKey = (AspectKey) key;
+ ConfiguredTargetValue configuredTargetValue =
+ (ConfiguredTargetValue)
+ memoizingEvaluator.getExistingValue(aspectKey.getBaseConfiguredTargetKey());
+ actionGraphDump.dumpAspect(aspectValue, configuredTargetValue);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
@@ -840,20 +840,20 @@
memoizingEvaluator.getDoneValues().entrySet()) {
SkyKey key = skyKeyAndValue.getKey();
SkyValue skyValue = skyKeyAndValue.getValue();
- SkyFunctionName functionName = key.functionName();
- try {
+ if (skyValue == null) {
// The skyValue may be null in case analysis of the previous build failed.
- if (skyValue != null) {
- if (functionName.equals(SkyFunctions.CONFIGURED_TARGET)) {
- actionGraphDump.dumpConfiguredTarget((ConfiguredTargetValue) skyValue);
- } else if (functionName.equals(SkyFunctions.ASPECT)) {
- AspectValue aspectValue = (AspectValue) skyValue;
- AspectKey aspectKey = (AspectKey) key;
- ConfiguredTargetValue configuredTargetValue =
- (ConfiguredTargetValue)
- memoizingEvaluator.getExistingValue(aspectKey.getBaseConfiguredTargetKey());
- actionGraphDump.dumpAspect(aspectValue, configuredTargetValue);
- }
+ continue;
+ }
+ try {
+ if (skyValue instanceof RuleConfiguredTargetValue) {
+ actionGraphDump.dumpConfiguredTarget((RuleConfiguredTargetValue) skyValue);
+ } else if (key.functionName().equals(SkyFunctions.ASPECT)) {
+ AspectValue aspectValue = (AspectValue) skyValue;
+ AspectKey aspectKey = (AspectKey) key;
+ ConfiguredTargetValue configuredTargetValue =
+ (ConfiguredTargetValue)
+ memoizingEvaluator.getExistingValue(aspectKey.getBaseConfiguredTargetKey());
+ actionGraphDump.dumpAspect(aspectValue, configuredTargetValue);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
index 1a90a8a..2cce56f 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeBuildView.java
@@ -32,6 +32,7 @@
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.actions.ActionLookupValue;
+import com.google.devtools.build.lib.actions.AnalysisGraphStatsEvent;
import com.google.devtools.build.lib.actions.ArtifactFactory;
import com.google.devtools.build.lib.actions.ArtifactPrefixConflictException;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
@@ -59,6 +60,7 @@
import com.google.devtools.build.lib.analysis.config.CoreOptions;
import com.google.devtools.build.lib.analysis.config.FragmentClassSet;
import com.google.devtools.build.lib.bugreport.BugReport;
+import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEventId.ConfigurationId;
import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
import com.google.devtools.build.lib.causes.AnalysisFailedCause;
@@ -142,7 +144,7 @@
private BuildConfiguration topLevelHostConfiguration;
// Fragment-limited versions of the host configuration. It's faster to create/cache these here
// than to store them in Skyframe.
- private Map<BuildConfiguration, BuildConfiguration> hostConfigurationCache =
+ private final Map<BuildConfiguration, BuildConfiguration> hostConfigurationCache =
Maps.newConcurrentMap();
private BuildConfigurationCollection configurations;
@@ -174,8 +176,7 @@
public TotalAndConfiguredTargetOnlyMetric getEvaluatedCounts() {
return TotalAndConfiguredTargetOnlyMetric.create(
- progressReceiver.actionLookupValueCount.get(),
- progressReceiver.configuredTargetCount.get());
+ progressReceiver.configuredObjectCount.get(), progressReceiver.configuredTargetCount.get());
}
ConfiguredTargetFactory getConfiguredTargetFactory() {
@@ -448,12 +449,17 @@
// This operation is somewhat expensive, so we only do it if the graph might have changed in
// some way -- either we analyzed a new target or we invalidated an old one or are building
// targets together that haven't been built before.
+ SkyframeExecutor.AnalysisTraversalResult analysisTraversalResult =
+ skyframeExecutor.getActionLookupValuesInBuild(ctKeys, aspectKeys);
ArtifactConflictFinder.ActionConflictsAndStats conflictsAndStats =
ArtifactConflictFinder.findAndStoreArtifactConflicts(
- skyframeExecutor.getActionLookupValuesInBuild(ctKeys, aspectKeys),
- strictConflictChecks,
- actionKeyContext);
- eventBus.post(conflictsAndStats.getStats());
+ analysisTraversalResult.getActionShards(), strictConflictChecks, actionKeyContext);
+ BuildEventStreamProtos.BuildMetrics.BuildGraphMetrics buildGraphMetrics =
+ analysisTraversalResult
+ .getMetrics()
+ .setOutputArtifactCount(conflictsAndStats.getOutputArtifactCount())
+ .build();
+ eventBus.post(new AnalysisGraphStatsEvent(buildGraphMetrics));
actionConflicts = conflictsAndStats.getConflicts();
someActionLookupValueEvaluated = false;
}
@@ -1135,7 +1141,7 @@
}
private final class ActionLookupValueProgressReceiver implements EvaluationProgressReceiver {
- private final AtomicInteger actionLookupValueCount = new AtomicInteger();
+ private final AtomicInteger configuredObjectCount = new AtomicInteger();
private final AtomicInteger actionCount = new AtomicInteger();
private final AtomicInteger configuredTargetCount = new AtomicInteger();
private final AtomicInteger configuredTargetActionCount = new AtomicInteger();
@@ -1165,16 +1171,17 @@
}
switch (state) {
case BUILT:
+ if (!evaluationSuccessState.get().succeeded()) {
+ return;
+ }
+ configuredObjectCount.incrementAndGet();
boolean isConfiguredTarget = skyKey.functionName().equals(SkyFunctions.CONFIGURED_TARGET);
- if (evaluationSuccessState.get().succeeded()) {
- actionLookupValueCount.incrementAndGet();
- if (isConfiguredTarget) {
- configuredTargetCount.incrementAndGet();
- }
- // During multithreaded operation, this is only set to true, so no concurrency issues.
- someActionLookupValueEvaluated = true;
+ if (isConfiguredTarget) {
+ configuredTargetCount.incrementAndGet();
}
if (newValue instanceof ActionLookupValue) {
+ // During multithreaded operation, this is only set to true, so no concurrency issues.
+ someActionLookupValueEvaluated = true;
int numActions = ((ActionLookupValue) newValue).getNumActions();
actionCount.addAndGet(numActions);
if (isConfiguredTarget) {
@@ -1190,7 +1197,7 @@
}
public void reset() {
- actionLookupValueCount.set(0);
+ configuredObjectCount.set(0);
actionCount.set(0);
configuredTargetCount.set(0);
configuredTargetActionCount.set(0);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index 0965be7..74c0d5b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -15,6 +15,7 @@
import static com.google.devtools.build.lib.concurrent.Uninterruptibles.callUninterruptibly;
import static com.google.devtools.build.lib.skyframe.ArtifactConflictFinder.ACTION_CONFLICTS;
+import static com.google.devtools.build.lib.skyframe.ArtifactConflictFinder.NUM_JOBS;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
@@ -97,10 +98,14 @@
import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
import com.google.devtools.build.lib.analysis.config.transitions.NoTransition;
import com.google.devtools.build.lib.analysis.config.transitions.NullTransition;
+import com.google.devtools.build.lib.analysis.configuredtargets.InputFileConfiguredTarget;
import com.google.devtools.build.lib.analysis.configuredtargets.MergedConfiguredTarget;
+import com.google.devtools.build.lib.analysis.configuredtargets.OutputFileConfiguredTarget;
import com.google.devtools.build.lib.analysis.starlark.StarlarkTransition;
import com.google.devtools.build.lib.analysis.starlark.StarlarkTransition.TransitionException;
+import com.google.devtools.build.lib.bugreport.BugReport;
import com.google.devtools.build.lib.bugreport.BugReporter;
+import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
@@ -108,6 +113,7 @@
import com.google.devtools.build.lib.collect.compacthashset.CompactHashSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetExpander;
import com.google.devtools.build.lib.concurrent.NamedForkJoinPool;
+import com.google.devtools.build.lib.concurrent.Sharder;
import com.google.devtools.build.lib.concurrent.ThreadSafety;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadCompatible;
import com.google.devtools.build.lib.events.ErrorSensingEventHandler;
@@ -1090,7 +1096,17 @@
}
// ctValue may be null if target was not successfully analyzed.
if (ctValue != null) {
- ctValue.clear(!topLevelTargets.contains(ctValue.getConfiguredTarget()));
+ if (!(ctValue instanceof ActionLookupValue)
+ && discardType.discardsLoading()
+ && !topLevelTargets.contains(ctValue.getConfiguredTarget())) {
+ // If loading is already being deleted, deleting these nodes doesn't hurt. Morally
+ // we should always be able to delete these, since they're not used for execution,
+ // but it leaves the graph inconsistent, and the --discard_analysis_cache with
+ // --track_incremental_state case isn't worth optimizing for.
+ it.remove();
+ } else {
+ ctValue.clear(!topLevelTargets.contains(ctValue.getConfiguredTarget()));
+ }
}
} else if (functionName.equals(SkyFunctions.ASPECT)) {
AspectValue aspectValue;
@@ -3142,18 +3158,24 @@
return ExecutionFinishedEvent.builderWithDefaults();
}
- final Iterable<ActionLookupValue> getActionLookupValuesInBuild(
+ final AnalysisTraversalResult getActionLookupValuesInBuild(
List<ConfiguredTargetKey> topLevelCtKeys, List<AspectValueKey> aspectKeys)
throws InterruptedException {
+ AnalysisTraversalResult result = new AnalysisTraversalResult();
if (!isAnalysisIncremental()) {
- // If we do not track incremental state we do not have graph edges, so we cannot traverse the
- // graph and find only actions in the current build. In this case we can simply return all
- // ActionLookupValues in the graph, since the graph's lifetime is a single build anyway.
- return Iterables.filter(memoizingEvaluator.getDoneValues().values(), ActionLookupValue.class);
+ // If we do not have incremental analysis state we do not have graph edges, so we cannot
+ // traverse the graph and find only actions in the current build. In this case we can simply
+ // return all ActionLookupValues in the graph, since the graph's lifetime is a single build
+ // anyway.
+ for (Map.Entry<SkyKey, SkyValue> entry : memoizingEvaluator.getDoneValues().entrySet()) {
+ if ((entry.getKey() instanceof ActionLookupKey) && entry.getValue() != null) {
+ result.accumulate(entry.getValue(), (ActionLookupKey) entry.getKey());
+ }
+ }
+ return result;
}
WalkableGraph walkableGraph = SkyframeExecutorWrappingWalkableGraph.of(this);
Set<SkyKey> seen = CompactHashSet.create();
- List<ActionLookupValue> result = new ArrayList<>();
for (ConfiguredTargetKey key : topLevelCtKeys) {
findActionsRecursively(walkableGraph, key, seen, result);
}
@@ -3163,22 +3185,95 @@
return result;
}
+ static class AnalysisTraversalResult {
+ // Some metrics indicate this is a rough average # of ALVs in a build.
+ private final Sharder<ActionLookupValue> actionShards = new Sharder<>(NUM_JOBS, 200_000);
+
+ // Metrics.
+ private int configuredObjectCount = 0;
+ private int configuredTargetCount = 0;
+ private int actionCount = 0;
+ private int actionCountNotIncludingAspects = 0;
+ private int inputFileConfiguredTargetCount = 0;
+ private int outputFileConfiguredTargetCount = 0;
+ private int otherConfiguredTargetCount = 0;
+
+ private AnalysisTraversalResult() {}
+
+ private void accumulate(SkyValue value, ActionLookupKey keyForDebugging) {
+ boolean isConfiguredTarget = value instanceof ConfiguredTargetValue;
+ boolean isActionLookupValue = value instanceof ActionLookupValue;
+ if (!isConfiguredTarget && !isActionLookupValue) {
+ BugReport.sendBugReport(
+ new IllegalStateException(
+ String.format(
+ "Should only be called with ConfiguredTargetValue or ActionLookupValue: %s %s"
+ + " %s",
+ value.getClass(), keyForDebugging, value)));
+ return;
+ }
+ configuredObjectCount++;
+ if (isConfiguredTarget) {
+ configuredTargetCount++;
+ }
+ if (isActionLookupValue) {
+ ActionLookupValue alv = (ActionLookupValue) value;
+ int numActions = alv.getNumActions();
+ actionCount += numActions;
+ if (isConfiguredTarget) {
+ actionCountNotIncludingAspects += numActions;
+ }
+ actionShards.add(alv);
+ return;
+ }
+ if (!(value instanceof NonRuleConfiguredTargetValue)) {
+ BugReport.sendBugReport(
+ new IllegalStateException(
+ String.format(
+ "Unexpected value type: %s %s %s", value.getClass(), keyForDebugging, value)));
+ return;
+ }
+ ConfiguredTarget configuredTarget =
+ ((NonRuleConfiguredTargetValue) value).getConfiguredTarget();
+ if (configuredTarget instanceof InputFileConfiguredTarget) {
+ inputFileConfiguredTargetCount++;
+ } else if (configuredTarget instanceof OutputFileConfiguredTarget) {
+ outputFileConfiguredTargetCount++;
+ } else {
+ otherConfiguredTargetCount++;
+ }
+ }
+
+ Sharder<ActionLookupValue> getActionShards() {
+ return actionShards;
+ }
+
+ BuildEventStreamProtos.BuildMetrics.BuildGraphMetrics.Builder getMetrics() {
+ return BuildEventStreamProtos.BuildMetrics.BuildGraphMetrics.newBuilder()
+ .setActionLookupValueCount(configuredObjectCount)
+ .setActionLookupValueCountNotIncludingAspects(configuredTargetCount)
+ .setActionCount(actionCount)
+ .setActionCountNotIncludingAspects(actionCountNotIncludingAspects)
+ .setInputFileConfiguredTargetCount(inputFileConfiguredTargetCount)
+ .setOutputFileConfiguredTargetCount(outputFileConfiguredTargetCount)
+ .setOtherConfiguredTargetCount(otherConfiguredTargetCount);
+ }
+ }
+
private static void findActionsRecursively(
- WalkableGraph walkableGraph, SkyKey key, Set<SkyKey> seen, List<ActionLookupValue> result)
+ WalkableGraph walkableGraph, SkyKey key, Set<SkyKey> seen, AnalysisTraversalResult result)
throws InterruptedException {
if (!(key instanceof ActionLookupKey) || !seen.add(key)) {
- // The subgraph of dependencies of ActionLookupValues never has a non-ActionLookupValue
- // depending on an ActionLookupValue. So we can skip any non-ActionLookupValues in the
- // traversal as an optimization.
+ // The subgraph of dependencies of ActionLookupKeys never has a non-ActionLookupKey depending
+ // on an ActionLookupKey. So we can skip any non-ActionLookupKeys in the traversal as an
+ // optimization.
return;
}
SkyValue value = walkableGraph.getValue(key);
if (value == null) {
return; // The value failed to evaluate.
}
- if (value instanceof ActionLookupValue) {
- result.add((ActionLookupValue) value);
- }
+ result.accumulate(value, (ActionLookupKey) key);
for (SkyKey dep : walkableGraph.getDirectDeps(key)) {
findActionsRecursively(walkableGraph, dep, seen, result);
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java
index 05b46ba..3ec30db 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/ActionGraphDump.java
@@ -36,6 +36,7 @@
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.query2.aquery.AqueryActionFilter;
import com.google.devtools.build.lib.query2.aquery.AqueryUtils;
+import com.google.devtools.build.lib.skyframe.RuleConfiguredTargetValue;
import com.google.devtools.build.lib.util.Pair;
import java.util.HashMap;
import java.util.List;
@@ -234,7 +235,7 @@
}
}
- public void dumpConfiguredTarget(ConfiguredTargetValue configuredTargetValue)
+ public void dumpConfiguredTarget(RuleConfiguredTargetValue configuredTargetValue)
throws CommandLineExpansionException, InterruptedException {
ConfiguredTarget configuredTarget = configuredTargetValue.getConfiguredTarget();
if (!includeInActionGraph(configuredTarget.getLabel().toString())) {
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java
index f43bead..7dd45a1 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/actiongraph/v2/ActionGraphDump.java
@@ -36,6 +36,7 @@
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.query2.aquery.AqueryActionFilter;
import com.google.devtools.build.lib.query2.aquery.AqueryUtils;
+import com.google.devtools.build.lib.skyframe.RuleConfiguredTargetValue;
import com.google.devtools.build.lib.util.Pair;
import java.io.IOException;
import java.util.HashMap;
@@ -49,11 +50,8 @@
* proto format.
*/
public class ActionGraphDump {
-
private final ActionKeyContext actionKeyContext = new ActionKeyContext();
private final Set<String> actionGraphTargets;
-
- private final KnownRuleClassStrings knownRuleClassStrings;
private final KnownArtifacts knownArtifacts;
private final KnownConfigurations knownConfigurations;
private final KnownNestedSets knownNestedSets;
@@ -96,7 +94,7 @@
this.includeParamFiles = includeParamFiles;
this.aqueryOutputHandler = aqueryOutputHandler;
- knownRuleClassStrings = new KnownRuleClassStrings(aqueryOutputHandler);
+ KnownRuleClassStrings knownRuleClassStrings = new KnownRuleClassStrings(aqueryOutputHandler);
knownArtifacts = new KnownArtifacts(aqueryOutputHandler);
knownConfigurations = new KnownConfigurations(aqueryOutputHandler);
knownNestedSets = new KnownNestedSets(aqueryOutputHandler, knownArtifacts);
@@ -245,7 +243,7 @@
}
}
- public void dumpConfiguredTarget(ConfiguredTargetValue configuredTargetValue)
+ public void dumpConfiguredTarget(RuleConfiguredTargetValue configuredTargetValue)
throws CommandLineExpansionException, InterruptedException, IOException {
ConfiguredTarget configuredTarget = configuredTargetValue.getConfiguredTarget();
if (!includeInActionGraph(configuredTarget.getLabel().toString())) {