Skip to content

Commit 14abe4f

Browse files
alexjskiphilwo
authored andcommitted
Allow DiffAwareness to share precomputed information about the workspace and
propagate it to the `WorkspaceStatusAction`. Each successful Bazel build issue 2 `BuildInfo` events -- one based on the result of running the command indicated by `workspace_status_command` and a dummy one based on a subset of available information. Receivers of those discard all but the first one. If a build fails before execution phase, the dummy event will be the only even issued, hence it will be used. `DiffAwareness` operates on the workspace to figure out the diffs and in the process probes properties of it. Allow `DiffAwareness` to share such information with the intention to make it available for the rest of the build. Propagate unanimous precomputed workspace information when it is available from `DiffAwareness` through the `DiffAwarenessManager` and `SkyframeExecutor` to `CommandEnvironment` and store it there to make it available for the rest of the build. Make precomputed workspace information available to the dummy `BuildInfo` event. PiperOrigin-RevId: 355072552
1 parent 9e7e592 commit 14abe4f

File tree

14 files changed

+277
-20
lines changed

14 files changed

+277
-20
lines changed

src/main/java/com/google/devtools/build/lib/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ java_library(
364364
"//src/main/java/com/google/devtools/build/lib/skyframe:skyframe_cluster",
365365
"//src/main/java/com/google/devtools/build/lib/skyframe:target_pattern_phase_value",
366366
"//src/main/java/com/google/devtools/build/lib/skyframe:top_down_action_cache",
367+
"//src/main/java/com/google/devtools/build/lib/skyframe:workspace_info",
367368
"//src/main/java/com/google/devtools/build/lib/unix",
368369
"//src/main/java/com/google/devtools/build/lib/util",
369370
"//src/main/java/com/google/devtools/build/lib/util:TestType",

src/main/java/com/google/devtools/build/lib/analysis/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,13 +1196,15 @@ java_library(
11961196
"//src/main/java/com/google/devtools/build/lib/actions:artifacts",
11971197
"//src/main/java/com/google/devtools/build/lib/collect/nestedset",
11981198
"//src/main/java/com/google/devtools/build/lib/shell",
1199+
"//src/main/java/com/google/devtools/build/lib/skyframe:workspace_info",
11991200
"//src/main/java/com/google/devtools/build/lib/util",
12001201
"//src/main/java/com/google/devtools/build/lib/util:detailed_exit_code",
12011202
"//src/main/java/com/google/devtools/build/lib/vfs",
12021203
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
12031204
"//src/main/java/com/google/devtools/common/options",
12041205
"//src/main/protobuf:failure_details_java_proto",
12051206
"//third_party:guava",
1207+
"//third_party:jsr305",
12061208
],
12071209
)
12081210

src/main/java/com/google/devtools/build/lib/analysis/WorkspaceStatusAction.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
2727
import com.google.devtools.build.lib.server.FailureDetails.WorkspaceStatus;
2828
import com.google.devtools.build.lib.server.FailureDetails.WorkspaceStatus.Code;
29+
import com.google.devtools.build.lib.skyframe.WorkspaceInfoFromDiff;
2930
import com.google.devtools.build.lib.util.DetailedExitCode;
3031
import com.google.devtools.build.lib.util.OptionsUtils;
3132
import com.google.devtools.build.lib.vfs.FileSystemUtils;
@@ -40,6 +41,7 @@
4041
import java.util.HashMap;
4142
import java.util.List;
4243
import java.util.Map;
44+
import javax.annotation.Nullable;
4345

4446
/**
4547
* An action writing the workspace status files.
@@ -174,6 +176,10 @@ public interface Environment {
174176
public interface DummyEnvironment {
175177
Path getWorkspace();
176178

179+
/** Returns optional precomputed workspace info to include in the build info event. */
180+
@Nullable
181+
WorkspaceInfoFromDiff getWorkspaceInfoFromDiff();
182+
177183
String getBuildRequestId();
178184

179185
OptionsProvider getOptions();

src/main/java/com/google/devtools/build/lib/buildtool/BuildTool.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import com.google.devtools.build.lib.server.FailureDetails.BuildConfiguration;
5656
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
5757
import com.google.devtools.build.lib.skyframe.SequencedSkyframeExecutor;
58+
import com.google.devtools.build.lib.skyframe.WorkspaceInfoFromDiff;
5859
import com.google.devtools.build.lib.skyframe.actiongraph.v2.ActionGraphDump;
5960
import com.google.devtools.build.lib.skyframe.actiongraph.v2.AqueryOutputHandler;
6061
import com.google.devtools.build.lib.skyframe.actiongraph.v2.AqueryOutputHandler.OutputType;
@@ -274,6 +275,12 @@ public String getBuildRequestId() {
274275
public OptionsProvider getOptions() {
275276
return env.getOptions();
276277
}
278+
279+
@Nullable
280+
@Override
281+
public WorkspaceInfoFromDiff getWorkspaceInfoFromDiff() {
282+
return env.getWorkspaceInfoFromDiff();
283+
}
277284
})));
278285
}
279286
}

src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
package com.google.devtools.build.lib.runtime;
1616

17+
import static com.google.common.base.Preconditions.checkState;
18+
1719
import com.google.common.annotations.VisibleForTesting;
1820
import com.google.common.base.Preconditions;
1921
import com.google.common.eventbus.EventBus;
@@ -40,6 +42,7 @@
4042
import com.google.devtools.build.lib.skyframe.SkyframeBuildView;
4143
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
4244
import com.google.devtools.build.lib.skyframe.TopDownActionCache;
45+
import com.google.devtools.build.lib.skyframe.WorkspaceInfoFromDiff;
4346
import com.google.devtools.build.lib.util.AbruptExitException;
4447
import com.google.devtools.build.lib.util.DetailedExitCode;
4548
import com.google.devtools.build.lib.util.io.OutErr;
@@ -100,6 +103,7 @@ public class CommandEnvironment {
100103
private TopDownActionCache topDownActionCache;
101104
private String workspaceName;
102105
private boolean hasSyncedPackageLoading = false;
106+
@Nullable private WorkspaceInfoFromDiff workspaceInfoFromDiff;
103107

104108
// This AtomicReference is set to:
105109
// - null, if neither BlazeModuleEnvironment#exit nor #precompleteCommand have been called
@@ -515,7 +519,7 @@ public String getWorkspaceName() {
515519
}
516520

517521
public void setWorkspaceName(String workspaceName) {
518-
Preconditions.checkState(this.workspaceName == null, "workspace name can only be set once");
522+
checkState(this.workspaceName == null, "workspace name can only be set once");
519523
this.workspaceName = workspaceName;
520524
eventBus.post(new ExecRootEvent(getExecRoot()));
521525
}
@@ -579,6 +583,18 @@ public void setOutputServiceForTesting(@Nullable OutputService outputService) {
579583
this.outputService = outputService;
580584
}
581585

586+
/**
587+
* Returns precomputed workspace information or null.
588+
*
589+
* <p>Precomputed workspace info is an optimization allowing to share information about the
590+
* workspace if it was derived at the time of synchronizing the workspace. This way we can make it
591+
* available earlier during the build and avoid retrieving it again.
592+
*/
593+
@Nullable
594+
public WorkspaceInfoFromDiff getWorkspaceInfoFromDiff() {
595+
return workspaceInfoFromDiff;
596+
}
597+
582598
public ActionCache getPersistentActionCache() throws IOException {
583599
return workspace.getPersistentActionCache(reporter);
584600
}
@@ -677,16 +693,17 @@ public void syncPackageLoading(OptionsProvider options)
677693
"We should never call this method more than once over the course of a single command");
678694
}
679695
hasSyncedPackageLoading = true;
680-
getSkyframeExecutor()
681-
.sync(
682-
reporter,
683-
options.getOptions(PackageOptions.class),
684-
packageLocator,
685-
options.getOptions(BuildLanguageOptions.class),
686-
getCommandId(),
687-
clientEnv,
688-
timestampGranularityMonitor,
689-
options);
696+
workspaceInfoFromDiff =
697+
getSkyframeExecutor()
698+
.sync(
699+
reporter,
700+
options.getOptions(PackageOptions.class),
701+
packageLocator,
702+
options.getOptions(BuildLanguageOptions.class),
703+
getCommandId(),
704+
clientEnv,
705+
timestampGranularityMonitor,
706+
options);
690707
}
691708

692709
public void recordLastExecutionTime() {

src/main/java/com/google/devtools/build/lib/skyframe/BUILD

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ java_library(
213213
":tree_artifact_value",
214214
":unloaded_toolchain_context",
215215
":unloaded_toolchain_context_impl",
216+
":workspace_info",
216217
":workspace_name_function",
217218
":workspace_name_value",
218219
":workspace_status_function",
@@ -1278,6 +1279,7 @@ java_library(
12781279
deps = [
12791280
":broken_diff_awareness_exception",
12801281
":incompatible_view_exception",
1282+
":workspace_info",
12811283
"//src/main/java/com/google/devtools/build/lib/vfs",
12821284
"//src/main/java/com/google/devtools/common/options",
12831285
"//third_party:jsr305",
@@ -1291,6 +1293,7 @@ java_library(
12911293
":broken_diff_awareness_exception",
12921294
":diff_awareness",
12931295
":incompatible_view_exception",
1296+
":workspace_info",
12941297
"//src/main/java/com/google/devtools/build/lib/events",
12951298
"//src/main/java/com/google/devtools/build/lib/vfs",
12961299
"//src/main/java/com/google/devtools/common/options",
@@ -2767,6 +2770,11 @@ java_library(
27672770
],
27682771
)
27692772

2773+
java_library(
2774+
name = "workspace_info",
2775+
srcs = ["WorkspaceInfoFromDiff.java"],
2776+
)
2777+
27702778
java_library(
27712779
name = "workspace_name_function",
27722780
srcs = ["WorkspaceNameFunction.java"],

src/main/java/com/google/devtools/build/lib/skyframe/BrokenDiffAwarenessException.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// limitations under the License.
1414
package com.google.devtools.build.lib.skyframe;
1515

16-
import com.google.common.base.Preconditions;
16+
import static com.google.common.base.Preconditions.checkNotNull;
1717

1818
/**
1919
* Thrown on {@link DiffAwareness#getDiff} to indicate that something is wrong with the
@@ -22,6 +22,10 @@
2222
public class BrokenDiffAwarenessException extends Exception {
2323

2424
public BrokenDiffAwarenessException(String msg) {
25-
super(Preconditions.checkNotNull(msg));
25+
super(checkNotNull(msg));
26+
}
27+
28+
public BrokenDiffAwarenessException(String msg, Throwable cause) {
29+
super(checkNotNull(msg), cause);
2630
}
2731
}

src/main/java/com/google/devtools/build/lib/skyframe/DiffAwareness.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ public interface Factory {
4545

4646
/** Opaque view of the filesystem under a package path entry at a specific point in time. */
4747
interface View {
48+
/** Returns workspace info unanimously associated with the package path or null. */
49+
@Nullable
50+
default WorkspaceInfoFromDiff getWorkspaceInfo() {
51+
return null;
52+
}
4853
}
4954

5055
/**

src/main/java/com/google/devtools/build/lib/skyframe/DiffAwarenessManager.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public void reset() {
6969
public interface ProcessableModifiedFileSet {
7070
ModifiedFileSet getModifiedFileSet();
7171

72+
@Nullable
73+
WorkspaceInfoFromDiff getWorkspaceInfo();
74+
7275
/**
7376
* This should be called when the changes have been noted. Otherwise, the result from the next
7477
* call to {@link #getDiff} will be from the baseline of the old, unprocessed, diff.
@@ -99,7 +102,7 @@ public ProcessableModifiedFileSet getDiff(
99102
if (baselineView == null) {
100103
logger.atInfo().log("Initial baseline view for %s is %s", pathEntry, newView);
101104
diffAwarenessState.baselineView = newView;
102-
return BrokenProcessableModifiedFileSet.INSTANCE;
105+
return new InitialModifiedFileSet(newView.getWorkspaceInfo());
103106
}
104107

105108
ModifiedFileSet diff;
@@ -172,6 +175,12 @@ public ModifiedFileSet getModifiedFileSet() {
172175
return modifiedFileSet;
173176
}
174177

178+
@Nullable
179+
@Override
180+
public WorkspaceInfoFromDiff getWorkspaceInfo() {
181+
return nextView.getWorkspaceInfo();
182+
}
183+
175184
@Override
176185
public void markProcessed() {
177186
DiffAwarenessState diffAwarenessState = currentDiffAwarenessStates.get(pathEntry);
@@ -191,6 +200,36 @@ public ModifiedFileSet getModifiedFileSet() {
191200
return ModifiedFileSet.EVERYTHING_MODIFIED;
192201
}
193202

203+
@Nullable
204+
@Override
205+
public WorkspaceInfoFromDiff getWorkspaceInfo() {
206+
return null;
207+
}
208+
209+
@Override
210+
public void markProcessed() {}
211+
}
212+
213+
/** Modified file set for a clean build. */
214+
private static class InitialModifiedFileSet implements ProcessableModifiedFileSet {
215+
216+
@Nullable private final WorkspaceInfoFromDiff workspaceInfo;
217+
218+
InitialModifiedFileSet(@Nullable WorkspaceInfoFromDiff workspaceInfo) {
219+
this.workspaceInfo = workspaceInfo;
220+
}
221+
222+
@Override
223+
public ModifiedFileSet getModifiedFileSet() {
224+
return ModifiedFileSet.EVERYTHING_MODIFIED;
225+
}
226+
227+
@Nullable
228+
@Override
229+
public WorkspaceInfoFromDiff getWorkspaceInfo() {
230+
return workspaceInfo;
231+
}
232+
194233
@Override
195234
public void markProcessed() {
196235
}

src/main/java/com/google/devtools/build/lib/skyframe/SequencedSkyframeExecutor.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,9 @@ public RecordingDifferencer getDifferencerForTesting() {
227227
return recordingDiffer;
228228
}
229229

230+
@Nullable
230231
@Override
231-
public void sync(
232+
public WorkspaceInfoFromDiff sync(
232233
ExtendedEventHandler eventHandler,
233234
PackageOptions packageOptions,
234235
PathPackageLocator packageLocator,
@@ -263,11 +264,13 @@ public void sync(
263264
tsgm,
264265
options);
265266
long startTime = System.nanoTime();
266-
handleDiffs(eventHandler, packageOptions.checkOutputFiles, options);
267+
WorkspaceInfoFromDiff workspaceInfo =
268+
handleDiffs(eventHandler, packageOptions.checkOutputFiles, options);
267269
long stopTime = System.nanoTime();
268270
Profiler.instance().logSimpleTask(startTime, stopTime, ProfilerTask.INFO, "handleDiffs");
269271
long duration = stopTime - startTime;
270272
sourceDiffCheckingDuration = duration > 0 ? Duration.ofNanos(duration) : Duration.ZERO;
273+
return workspaceInfo;
271274
}
272275

273276
/**
@@ -342,7 +345,8 @@ public void handleDiffsForTesting(ExtendedEventHandler eventHandler)
342345
handleDiffs(eventHandler, /*checkOutputFiles=*/false, OptionsProvider.EMPTY);
343346
}
344347

345-
private void handleDiffs(
348+
@Nullable
349+
private WorkspaceInfoFromDiff handleDiffs(
346350
ExtendedEventHandler eventHandler, boolean checkOutputFiles, OptionsProvider options)
347351
throws InterruptedException, AbruptExitException {
348352
TimestampGranularityMonitor tsgm = this.tsgm.get();
@@ -355,13 +359,18 @@ private void handleDiffs(
355359
invalidateCachedWorkspacePathsStates();
356360
}
357361

362+
WorkspaceInfoFromDiff workspaceInfo = null;
358363
Map<Root, DiffAwarenessManager.ProcessableModifiedFileSet> modifiedFilesByPathEntry =
359364
Maps.newHashMap();
360365
Set<Pair<Root, DiffAwarenessManager.ProcessableModifiedFileSet>>
361366
pathEntriesWithoutDiffInformation = Sets.newHashSet();
362-
for (Root pathEntry : pkgLocator.get().getPathEntries()) {
367+
ImmutableList<Root> pkgRoots = pkgLocator.get().getPathEntries();
368+
for (Root pathEntry : pkgRoots) {
363369
DiffAwarenessManager.ProcessableModifiedFileSet modifiedFileSet =
364370
diffAwarenessManager.getDiff(eventHandler, pathEntry, options);
371+
if (pkgRoots.size() == 1) {
372+
workspaceInfo = modifiedFileSet.getWorkspaceInfo();
373+
}
365374
if (modifiedFileSet.getModifiedFileSet().treatEverythingAsModified()) {
366375
pathEntriesWithoutDiffInformation.add(Pair.of(pathEntry, modifiedFileSet));
367376
} else {
@@ -382,6 +391,7 @@ private void handleDiffs(
382391
managedDirectoriesChanged,
383392
fsvcThreads);
384393
handleClientEnvironmentChanges();
394+
return workspaceInfo;
385395
}
386396

387397
/**

src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2630,8 +2630,13 @@ ActionExecutionStatusReporter getActionExecutionStatusReporterForTesting() {
26302630

26312631
/**
26322632
* Initializes and syncs the graph with the given options, readying it for the next evaluation.
2633+
*
2634+
* <p>Returns precomputed information about the workspace if it is available at this stage. This
2635+
* is an optimization allowing implementations which have such information to make it available
2636+
* early in the build.
26332637
*/
2634-
public void sync(
2638+
@Nullable
2639+
public WorkspaceInfoFromDiff sync(
26352640
ExtendedEventHandler eventHandler,
26362641
PackageOptions packageOptions,
26372642
PathPackageLocator pathPackageLocator,
@@ -2657,6 +2662,7 @@ public void sync(
26572662
dropConfiguredTargetsNow(eventHandler);
26582663
lastAnalysisDiscarded = false;
26592664
}
2665+
return null;
26602666
}
26612667

26622668
protected void syncPackageLoading(
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2021 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package com.google.devtools.build.lib.skyframe;
15+
16+
/** Information for a workspace computed at the time of collecting diff. */
17+
public interface WorkspaceInfoFromDiff {}

0 commit comments

Comments
 (0)