Have ExecutionFinishedEvent contain the number of source files manually checked for changes because of a lack of precise diff information.
PiperOrigin-RevId: 291789856
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ExecutionFinishedEvent.java b/src/main/java/com/google/devtools/build/lib/skyframe/ExecutionFinishedEvent.java
index 2853756..4c0b79a 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ExecutionFinishedEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ExecutionFinishedEvent.java
@@ -13,47 +13,52 @@
// limitations under the License.
package com.google.devtools.build.lib.skyframe;
-import com.google.common.base.Preconditions;
+import com.google.auto.value.AutoValue;
import java.time.Duration;
/**
- * Event signaling the end of the execution phase. Contains statistics about the action cache,
- * the metadata cache and about last file save times.
+ * Event signaling the end of the execution phase. Contains statistics about the action cache, the
+ * metadata cache and about last file save times.
*/
-public class ExecutionFinishedEvent {
+@AutoValue
+public abstract class ExecutionFinishedEvent {
public static final ExecutionFinishedEvent EMPTY =
- new ExecutionFinishedEvent(0, 0, Duration.ZERO, Duration.ZERO);
+ builder()
+ .setOutputDirtyFiles(0)
+ .setOutputModifiedFilesDuringPreviousBuild(0)
+ .setSourceDiffCheckingDuration(Duration.ZERO)
+ .setNumSourceFilesCheckedBecauseOfMissingDiffs(0)
+ .setOutputTreeDiffCheckingDuration(Duration.ZERO)
+ .build();
- private final int outputDirtyFiles;
- private final int outputModifiedFilesDuringPreviousBuild;
- private final Duration sourceDiffCheckingDuration;
- private final Duration outputTreeDiffCheckingDuration;
+ public abstract int outputDirtyFiles();
- ExecutionFinishedEvent(
- int outputDirtyFiles,
- int outputModifiedFilesDuringPreviousBuild,
- Duration sourceDiffCheckingDuration,
- Duration outputTreeDiffCheckingDuration) {
- this.outputDirtyFiles = outputDirtyFiles;
- this.outputModifiedFilesDuringPreviousBuild = outputModifiedFilesDuringPreviousBuild;
- this.sourceDiffCheckingDuration = Preconditions.checkNotNull(sourceDiffCheckingDuration);
- this.outputTreeDiffCheckingDuration =
- Preconditions.checkNotNull(outputTreeDiffCheckingDuration);
+ public abstract int outputModifiedFilesDuringPreviousBuild();
+
+ public abstract Duration sourceDiffCheckingDuration();
+
+ public abstract int numSourceFilesCheckedBecauseOfMissingDiffs();
+
+ public abstract Duration outputTreeDiffCheckingDuration();
+
+ static Builder builder() {
+ return new AutoValue_ExecutionFinishedEvent.Builder();
}
- public int getOutputDirtyFiles() {
- return outputDirtyFiles;
- }
+ @AutoValue.Builder
+ abstract static class Builder {
+ abstract Builder setOutputDirtyFiles(int outputDirtyFiles);
- public int getOutputModifiedFilesDuringPreviousBuild() {
- return outputModifiedFilesDuringPreviousBuild;
- }
+ abstract Builder setOutputModifiedFilesDuringPreviousBuild(
+ int outputModifiedFilesDuringPreviousBuild);
- public Duration getSourceDiffCheckingDuration() {
- return sourceDiffCheckingDuration;
- }
+ abstract Builder setSourceDiffCheckingDuration(Duration sourceDiffCheckingDuration);
- public Duration getOutputTreeDiffCheckingDuration() {
- return outputTreeDiffCheckingDuration;
+ abstract Builder setNumSourceFilesCheckedBecauseOfMissingDiffs(
+ int numSourceFilesCheckedBecauseOfMissingDiffs);
+
+ abstract Builder setOutputTreeDiffCheckingDuration(Duration outputTreeDiffCheckingDuration);
+
+ abstract ExecutionFinishedEvent build();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java b/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java
index 6c5342b..44665ee 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FilesystemValueChecker.java
@@ -45,6 +45,7 @@
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Symlinks;
import com.google.devtools.build.skyframe.Differencer;
+import com.google.devtools.build.skyframe.Differencer.DiffWithDelta.Delta;
import com.google.devtools.build.skyframe.FunctionHermeticity;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
@@ -99,8 +100,9 @@
*/
// TODO(bazel-team): Refactor these methods so that FilesystemValueChecker only operates on a
// WalkableGraph.
- Differencer.DiffWithDelta getDirtyKeys(Map<SkyKey, SkyValue> valuesMap,
- SkyValueDirtinessChecker dirtinessChecker) throws InterruptedException {
+ ImmutableBatchDirtyResult getDirtyKeys(
+ Map<SkyKey, SkyValue> valuesMap, SkyValueDirtinessChecker dirtinessChecker)
+ throws InterruptedException {
return getDirtyValues(new MapBackedValueFetcher(valuesMap), valuesMap.keySet(),
dirtinessChecker, /*checkMissingValues=*/false);
}
@@ -109,9 +111,11 @@
* Returns a {@link Differencer.DiffWithDelta} containing keys that are dirty according to the
* passed-in {@code dirtinessChecker}.
*/
- public Differencer.DiffWithDelta getNewAndOldValues(Map<SkyKey, SkyValue> valuesMap,
- Iterable<SkyKey> keys, SkyValueDirtinessChecker dirtinessChecker)
- throws InterruptedException {
+ public ImmutableBatchDirtyResult getNewAndOldValues(
+ Map<SkyKey, SkyValue> valuesMap,
+ Iterable<SkyKey> keys,
+ SkyValueDirtinessChecker dirtinessChecker)
+ throws InterruptedException {
return getDirtyValues(new MapBackedValueFetcher(valuesMap), keys,
dirtinessChecker, /*checkMissingValues=*/true);
}
@@ -478,19 +482,22 @@
return headPath != null && headPath.startsWith(artifactExecPath);
}
- private BatchDirtyResult getDirtyValues(ValueFetcher fetcher,
- Iterable<SkyKey> keys, final SkyValueDirtinessChecker checker,
- final boolean checkMissingValues) throws InterruptedException {
+ private ImmutableBatchDirtyResult getDirtyValues(
+ ValueFetcher fetcher,
+ Iterable<SkyKey> keys,
+ final SkyValueDirtinessChecker checker,
+ final boolean checkMissingValues)
+ throws InterruptedException {
ExecutorService executor =
Executors.newFixedThreadPool(
DIRTINESS_CHECK_THREADS,
new ThreadFactoryBuilder().setNameFormat("FileSystem Value Invalidator %d").build());
- final BatchDirtyResult batchResult = new BatchDirtyResult();
ThrowableRecordingRunnableWrapper wrapper =
new ThrowableRecordingRunnableWrapper("FilesystemValueChecker#getDirtyValues");
final AtomicInteger numKeysScanned = new AtomicInteger(0);
final AtomicInteger numKeysChecked = new AtomicInteger(0);
+ MutableBatchDirtyResult batchResult = new MutableBatchDirtyResult(numKeysChecked);
ElapsedTimeReceiver elapsedTimeReceiver =
elapsedTimeNanos -> {
if (elapsedTimeNanos > 0) {
@@ -540,19 +547,57 @@
throw new InterruptedException();
}
}
- return batchResult;
+ return batchResult.toImmutable();
+ }
+
+ static class ImmutableBatchDirtyResult implements Differencer.DiffWithDelta {
+ private final Collection<SkyKey> dirtyKeysWithoutNewValues;
+ private final Map<SkyKey, Delta> dirtyKeysWithNewAndOldValues;
+ private final int numKeysChecked;
+
+ private ImmutableBatchDirtyResult(
+ Collection<SkyKey> dirtyKeysWithoutNewValues,
+ Map<SkyKey, Delta> dirtyKeysWithNewAndOldValues,
+ int numKeysChecked) {
+ this.dirtyKeysWithoutNewValues = dirtyKeysWithoutNewValues;
+ this.dirtyKeysWithNewAndOldValues = dirtyKeysWithNewAndOldValues;
+ this.numKeysChecked = numKeysChecked;
+ }
+
+ @Override
+ public Collection<SkyKey> changedKeysWithoutNewValues() {
+ return dirtyKeysWithoutNewValues;
+ }
+
+ @Override
+ public Map<SkyKey, Delta> changedKeysWithNewAndOldValues() {
+ return dirtyKeysWithNewAndOldValues;
+ }
+
+ @Override
+ public Map<SkyKey, SkyValue> changedKeysWithNewValues() {
+ return Delta.newValues(dirtyKeysWithNewAndOldValues);
+ }
+
+ int getNumKeysChecked() {
+ return numKeysChecked;
+ }
}
/**
- * Result of a batch call to {@link SkyValueDirtinessChecker#check}. Partitions the dirty
- * values based on whether we have a new value available for them or not.
+ * Result of a batch call to {@link SkyValueDirtinessChecker#check}. Partitions the dirty values
+ * based on whether we have a new value available for them or not.
*/
- private static class BatchDirtyResult implements Differencer.DiffWithDelta {
-
+ private static class MutableBatchDirtyResult {
private final Set<SkyKey> concurrentDirtyKeysWithoutNewValues =
Collections.newSetFromMap(new ConcurrentHashMap<SkyKey, Boolean>());
private final ConcurrentHashMap<SkyKey, Delta> concurrentDirtyKeysWithNewAndOldValues =
new ConcurrentHashMap<>();
+ private final AtomicInteger numChecked;
+
+ private MutableBatchDirtyResult(AtomicInteger numChecked) {
+ this.numChecked = numChecked;
+ }
private void add(SkyKey key, @Nullable SkyValue oldValue, @Nullable SkyValue newValue) {
if (newValue == null) {
@@ -566,19 +611,11 @@
}
}
- @Override
- public Collection<SkyKey> changedKeysWithoutNewValues() {
- return concurrentDirtyKeysWithoutNewValues;
- }
-
- @Override
- public Map<SkyKey, Delta> changedKeysWithNewAndOldValues() {
- return concurrentDirtyKeysWithNewAndOldValues;
- }
-
- @Override
- public Map<SkyKey, SkyValue> changedKeysWithNewValues() {
- return Delta.newValues(concurrentDirtyKeysWithNewAndOldValues);
+ private ImmutableBatchDirtyResult toImmutable() {
+ return new ImmutableBatchDirtyResult(
+ concurrentDirtyKeysWithoutNewValues,
+ concurrentDirtyKeysWithNewAndOldValues,
+ numChecked.get());
}
}
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 7f2df10..bea8cce 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
@@ -71,6 +71,7 @@
import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFileAction;
import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.ExternalFilesKnowledge;
import com.google.devtools.build.lib.skyframe.ExternalFilesHelper.FileType;
+import com.google.devtools.build.lib.skyframe.FilesystemValueChecker.ImmutableBatchDirtyResult;
import com.google.devtools.build.lib.skyframe.PackageFunction.ActionOnIOExceptionReadingBuildFile;
import com.google.devtools.build.lib.skyframe.PackageLookupFunction.CrossRepositoryLabelViolationStrategy;
import com.google.devtools.build.lib.skyframe.actiongraph.ActionGraphDump;
@@ -86,7 +87,6 @@
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.BuildDriver;
import com.google.devtools.build.skyframe.Differencer;
-import com.google.devtools.build.skyframe.Differencer.Diff;
import com.google.devtools.build.skyframe.EvaluationContext;
import com.google.devtools.build.skyframe.GraphInconsistencyReceiver;
import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator;
@@ -147,6 +147,7 @@
private int outputDirtyFiles;
private int modifiedFilesDuringPreviousBuild;
private Duration sourceDiffCheckingDuration = Duration.ofSeconds(-1L);
+ private int numSourceFilesCheckedBecauseOfMissingDiffs;
private Duration outputTreeDiffCheckingDuration = Duration.ofSeconds(-1L);
// If this is null then workspace header pre-calculation won't happen.
@@ -331,6 +332,7 @@
throws InterruptedException, AbruptExitException {
TimestampGranularityMonitor tsgm = this.tsgm.get();
modifiedFiles = 0;
+ numSourceFilesCheckedBecauseOfMissingDiffs = 0;
boolean managedDirectoriesChanged =
managedDirectoriesKnowledge != null && refreshWorkspaceHeader(eventHandler);
@@ -432,6 +434,7 @@
handleChangedFiles(
ImmutableList.of(pathEntry),
getDiff(tsgm, modifiedFileSet.modifiedSourceFiles(), pathEntry),
+ /*numSourceFilesCheckedIfDiffWasMissing=*/ 0,
managedDirectoriesChanged);
processableModifiedFileSet.markProcessed();
}
@@ -500,9 +503,9 @@
logger.info(
"About to scan skyframe graph checking for filesystem nodes of types "
+ Iterables.toString(fileTypesToCheck));
- Differencer.Diff diff;
+ ImmutableBatchDirtyResult batchDirtyResult;
try (SilentCloseable c = Profiler.instance().profile("fsvc.getDirtyKeys")) {
- diff =
+ batchDirtyResult =
fsvc.getDirtyKeys(
memoizingEvaluator.getValues(),
new UnionDirtinessChecker(
@@ -512,7 +515,11 @@
new ExternalDirtinessChecker(tmpExternalFilesHelper, fileTypesToCheck),
new MissingDiffDirtinessChecker(diffPackageRootsUnderWhichToCheck)))));
}
- handleChangedFiles(diffPackageRootsUnderWhichToCheck, diff, managedDirectoriesChanged);
+ handleChangedFiles(
+ diffPackageRootsUnderWhichToCheck,
+ batchDirtyResult,
+ /*numSourceFilesCheckedIfDiffWasMissing=*/ batchDirtyResult.getNumKeysChecked(),
+ managedDirectoriesChanged);
for (Pair<Root, DiffAwarenessManager.ProcessableModifiedFileSet> pair :
pathEntriesWithoutDiffInformation) {
@@ -527,7 +534,8 @@
private void handleChangedFiles(
Collection<Root> diffPackageRootsUnderWhichToCheck,
- Diff diff,
+ Differencer.Diff diff,
+ int numSourceFilesCheckedIfDiffWasMissing,
boolean managedDirectoriesChanged) {
int numWithoutNewValues = diff.changedKeysWithoutNewValues().size();
Iterable<SkyKey> keysToBeChangedLaterInThisBuild = diff.changedKeysWithoutNewValues();
@@ -552,6 +560,7 @@
recordingDiffer.inject(changedKeysWithNewValues);
modifiedFiles += getNumberOfModifiedFiles(keysToBeChangedLaterInThisBuild);
modifiedFiles += getNumberOfModifiedFiles(changedKeysWithNewValues.keySet());
+ numSourceFilesCheckedBecauseOfMissingDiffs += numSourceFilesCheckedIfDiffWasMissing;
incrementalBuildMonitor.accrue(keysToBeChangedLaterInThisBuild);
incrementalBuildMonitor.accrue(changedKeysWithNewValues.keySet());
}
@@ -855,11 +864,14 @@
@Override
public ExecutionFinishedEvent createExecutionFinishedEvent() {
ExecutionFinishedEvent result =
- new ExecutionFinishedEvent(
- outputDirtyFiles,
- modifiedFilesDuringPreviousBuild,
- sourceDiffCheckingDuration,
- outputTreeDiffCheckingDuration);
+ ExecutionFinishedEvent.builder()
+ .setOutputDirtyFiles(outputDirtyFiles)
+ .setOutputModifiedFilesDuringPreviousBuild(modifiedFilesDuringPreviousBuild)
+ .setSourceDiffCheckingDuration(sourceDiffCheckingDuration)
+ .setNumSourceFilesCheckedBecauseOfMissingDiffs(
+ numSourceFilesCheckedBecauseOfMissingDiffs)
+ .setOutputTreeDiffCheckingDuration(outputTreeDiffCheckingDuration)
+ .build();
outputDirtyFiles = 0;
modifiedFilesDuringPreviousBuild = 0;
sourceDiffCheckingDuration = Duration.ZERO;