Skip to content

Commit

Permalink
[7.3.0] Deduplicate locally executed path mapped spawns (#23069)
Browse files Browse the repository at this point in the history
When path mapping is enabled, different `Spawn`s in the same build can
have identical `RemoteAction.ActionKey`s and can thus provide remote
cache hits for each other. However, cache hits are only possible after
the first local execution has concluded and uploaded its result to the
cache.

To avoid unnecessary duplication of local work, the first `Spawn` for
each `RemoteAction.ActionKey` is tracked until its results have been
uploaded and all other concurrently scheduled `Spawn`s wait for it and
then copy over its local outputs.

Fixes #21043

Closes #22556.

PiperOrigin-RevId: 655097996
Change-Id: I4368f9210c67a306775164d252aae122d8b46f9b

Closes #23060
  • Loading branch information
fmeum authored Jul 29, 2024
1 parent 282ac62 commit ffe1df5
Show file tree
Hide file tree
Showing 12 changed files with 929 additions and 152 deletions.
143 changes: 143 additions & 0 deletions src/main/java/com/google/devtools/build/lib/actions/SpawnResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,149 @@ public Digest getDigest() {
}
}

/**
* A helper class for wrapping an existing {@link SpawnResult} and modifying a subset of its
* methods.
*/
class DelegateSpawnResult implements SpawnResult {
private final SpawnResult delegate;

public DelegateSpawnResult(SpawnResult delegate) {
this.delegate = delegate;
}

@Override
public boolean setupSuccess() {
return delegate.setupSuccess();
}

@Override
public boolean isCatastrophe() {
return delegate.isCatastrophe();
}

@Override
public Status status() {
return delegate.status();
}

@Override
public int exitCode() {
return delegate.exitCode();
}

@Override
@Nullable
public FailureDetail failureDetail() {
return delegate.failureDetail();
}

@Override
@Nullable
public String getExecutorHostName() {
return delegate.getExecutorHostName();
}

@Override
public String getRunnerName() {
return delegate.getRunnerName();
}

@Override
public String getRunnerSubtype() {
return delegate.getRunnerSubtype();
}

@Override
@Nullable
public Instant getStartTime() {
return delegate.getStartTime();
}

@Override
public int getWallTimeInMs() {
return delegate.getWallTimeInMs();
}

@Override
public int getUserTimeInMs() {
return delegate.getUserTimeInMs();
}

@Override
public int getSystemTimeInMs() {
return delegate.getSystemTimeInMs();
}

@Override
@Nullable
public Long getNumBlockOutputOperations() {
return delegate.getNumBlockOutputOperations();
}

@Override
@Nullable
public Long getNumBlockInputOperations() {
return delegate.getNumBlockInputOperations();
}

@Override
@Nullable
public Long getNumInvoluntaryContextSwitches() {
return delegate.getNumInvoluntaryContextSwitches();
}

@Override
@Nullable
public Long getMemoryInKb() {
return delegate.getMemoryInKb();
}

@Override
public SpawnMetrics getMetrics() {
return delegate.getMetrics();
}

@Override
public boolean isCacheHit() {
return delegate.isCacheHit();
}

@Override
public String getFailureMessage() {
return delegate.getFailureMessage();
}

@Override
@Nullable
public InputStream getInMemoryOutput(ActionInput output) {
return delegate.getInMemoryOutput(output);
}

@Override
public String getDetailMessage(
String message, boolean catastrophe, boolean forciblyRunRemotely) {
return delegate.getDetailMessage(message, catastrophe, forciblyRunRemotely);
}

@Override
@Nullable
public MetadataLog getActionMetadataLog() {
return delegate.getActionMetadataLog();
}

@Override
public boolean wasRemote() {
return delegate.wasRemote();
}

@Override
@Nullable
public Digest getDigest() {
return delegate.getDigest();
}
}

/** Builder class for {@link SpawnResult}. */
final class Builder {
private int exitCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ public ImmutableList<SpawnResult> exec(
? resultMessage
: CommandFailureUtils.describeCommandFailure(
executionOptions.verboseFailures, cwd, spawn);
throw new SpawnExecException(message, spawnResult, /*forciblyRunRemotely=*/ false);
throw new SpawnExecException(message, spawnResult, /* forciblyRunRemotely= */ false);
}
return ImmutableList.of(spawnResult);
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/google/devtools/build/lib/exec/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ java_library(
deps = [
":spawn_runner",
"//src/main/java/com/google/devtools/build/lib/actions",
"//src/main/java/com/google/devtools/build/lib/profiler",
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.google.devtools.build.lib.actions.ForbiddenActionInputException;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.SpawnResult;
import com.google.devtools.build.lib.actions.Spawns;
import com.google.devtools.build.lib.exec.SpawnRunner.SpawnExecutionContext;
import java.io.Closeable;
import java.io.IOException;
Expand Down
Loading

0 comments on commit ffe1df5

Please sign in to comment.