Filter spawn strategies by execution platform#24265
Filter spawn strategies by execution platform#24265Silic0nS0ldier wants to merge 2 commits intobazelbuild:masterfrom
Conversation
|
cc @katre |
|
@Silic0nS0ldier Can you please fix the test failures? (It looks like the execution platform is null in a bunch of places.) |
| : ImmutableSortedMap.of(); | ||
|
|
||
| if (spawn.getExecutionPlatform() == null | ||
| if ((spawn.getExecutionPlatform() == null || spawn.getExecutionPlatform().execProperties().isEmpty()) |
There was a problem hiding this comment.
Without this change, Command protos end up populating platform (a deprecated field) with an empty Platform, increasing the size of the overall message.
In JSON it looks something like { "platform": {} }.
This was caught by //src/test/java/com/google/devtools/build/lib/remote:RemoteTests.
src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/bazel/rules/BazelStrategyModule.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java
Outdated
Show resolved
Hide resolved
|
What's the status of this PR? |
01357a0 to
2dd0316
Compare
26efd49 to
18a0fe5
Compare
|
I didn't have much time to focus on this recently, but I do now. PR has been rebased and prior feedback implemented. This is now ready for review. |
katre
left a comment
There was a problem hiding this comment.
LGTM, But this review should be assigned to @gregestren since I am no longer on the Bazel team.
One comment to clarify the intended semantics, but overall this looks good.
src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java
Show resolved
Hide resolved
b834e0d to
9667ea5
Compare
|
@gregestren This is ready for review. |
katre
left a comment
There was a problem hiding this comment.
LGTM (with a few requests for clarification in docs and comments).
Needs to wait for a Bazel team member to approve and merge.
src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
Outdated
Show resolved
Hide resolved
src/main/java/com/google/devtools/build/lib/exec/SpawnStrategyRegistry.java
Show resolved
Hide resolved
592eefc to
27786ba
Compare
|
@Silic0nS0ldier What's the status? Happy to help if you need any! |
|
Waiting for review. |
|
@gregestren I'll do a review pass soon. Let's try to get this into Bazel 9 as it nicely complements the new default test toolchain to finally make "what's executed where" work |
|
@bazel-io fork 9.0.0 |
|
Checking in: I'll do a proper review Monday. Thanks for your ongoing patience @Silic0nS0ldier |
| } | ||
|
|
||
| private static class StrategyPlatformFilter { | ||
| private final StrategyMapper strategyMapper; |
There was a problem hiding this comment.
Yep, likely a leftover from an earlier prototype. I'll get it removed.
| } | ||
|
|
||
| ImmutableListMultimap.Builder<Label, SpawnStrategy> platformToStrategies = ImmutableListMultimap.builder(); | ||
| for (Map.Entry<Label, List<String>> entry : execPlatformFilters.entrySet()) { |
There was a problem hiding this comment.
The filters are a hash map and thus didn't have a defined iteration order, but here we produce an immutable collection that does. Could you pick one or the other?
There was a problem hiding this comment.
Iteration order should not matter for;
- The key (a platform
Label), since usage remains as a key and key order is not relied on. - The values (a list of spawn strategies, converted from
List<String>toImmutableList<SpawnStrategy>), since usage is only for filtering.
Realistically the values should be using ImmutableSet given order does not matter and usage is exclusively presence checks.
To that end, there is ImmutableSetMultimap.
EDIT: Provided SpawnStrategy is safe to hash.
There was a problem hiding this comment.
I can't see SpawnStrategy used as a map key nor set value, so changing to ImmutableSetMultimap may not be a trivial change. Better left to a PR after this IMO.
There was a problem hiding this comment.
It looks like this iterated at least to generate the info log above. The main problem with these "sequence-washed" collections is that future usage may start to rely on ordering based on the guarantees afforded by ImmutableCollection types. Using a LinkedHashMap would be a very simple fix.
There was a problem hiding this comment.
It looks like this iterated at least to generate the info log above. The main problem with these "sequence-washed" collections is that future usage may start to rely on ordering based on the guarantees afforded by ImmutableCollection types. Using a LinkedHashMap would be a very simple fix.
There was a problem hiding this comment.
FWIW I generally think we should always used LinkedHashMap unless there's some known performance / resource risk to doing so.
There was a problem hiding this comment.
Taking another look, this is not a problem (anti-pattern? code smell?) introduced by this PR. The exact same map-to-map operation is done for;
mnemonicToIdentifiersmnemonicToLocalDynamicIdentifiersmnemonicToRemoteDynamicIdentifiers
which are all iterating over HashMap<String, List<String>> lists.
The only place (currently) where map ordering can result in different behaviour is in logging (logSpawnStrategies and possibly in new SpawnStrategyRegistry).
I'm not against making changes to ensure stable ordering (especially given it is logged, inconsistent order can be a source of confusion) however I do think it is out of scope for this PR. The spawn registry is an important component so I'd personally like to keep the changeset as minimal as possible (less to step through if something breaks and a git bisect is necessary).
If everyone is happy, I'll raise a separate PR that addresses the map ordering concerns raised here (e.g. switching to LinkedHashMap).
There was a problem hiding this comment.
Sounds good to me, I couldn't tell from the diff that this was so invasive (same for the copy-on-write data structure).
There was a problem hiding this comment.
Sounds good to me, I couldn't tell from the diff that this was so invasive (same for the copy-on-write data structure).
There was a problem hiding this comment.
I've gone in a bit of a different direction with this feedback in #27975. Rather than stabilizing the implementation detail, I've added lexical sorting to all keys and sets that are order insensitive.
This way if a behavior change is implemented, it will be (at least a little) more obvious.
51b35fd to
ce39c90
Compare
| * Order from {@code candidateStrategies} is preserved. | ||
| */ | ||
| public <T extends SpawnStrategy> List<T> getStrategies( | ||
| Spawn spawn, List<T> candidateStrategies) { |
There was a problem hiding this comment.
| Spawn spawn, List<T> candidateStrategies) { | |
| Spawn spawn, Collection<T> candidateStrategies) { |
so that an `ImmutableCollection can be passed in directly without the copy-on-write adapter.
There was a problem hiding this comment.
Switching to Collection here is an easy enough change.
Removing the copy-on-write adapter is a lot more "viral" of a change, spreading all the way to SpawnStrategyRegistry.getStrategies(Spawn, EventHandler). A refactor such as that is deserving of it's own PR.
| } | ||
|
|
||
| ImmutableListMultimap.Builder<Label, SpawnStrategy> platformToStrategies = ImmutableListMultimap.builder(); | ||
| for (Map.Entry<Label, List<String>> entry : execPlatformFilters.entrySet()) { |
There was a problem hiding this comment.
It looks like this iterated at least to generate the info log above. The main problem with these "sequence-washed" collections is that future usage may start to rely on ordering based on the guarantees afforded by ImmutableCollection types. Using a LinkedHashMap would be a very simple fix.
| } | ||
|
|
||
| ImmutableListMultimap.Builder<Label, SpawnStrategy> platformToStrategies = ImmutableListMultimap.builder(); | ||
| for (Map.Entry<Label, List<String>> entry : execPlatformFilters.entrySet()) { |
There was a problem hiding this comment.
It looks like this iterated at least to generate the info log above. The main problem with these "sequence-washed" collections is that future usage may start to rely on ordering based on the guarantees afforded by ImmutableCollection types. Using a LinkedHashMap would be a very simple fix.
src/main/java/com/google/devtools/build/lib/analysis/platform/PlatformUtils.java
Show resolved
Hide resolved
| * <p>If the reason for selecting the context is worth mentioning to the user, logs a message | ||
| * using the given {@link Reporter}. | ||
| * | ||
| * NOTE: This method is public for Blaze, `getStrategies(Spawn, EventHandler)` must not be used in Bazel. |
There was a problem hiding this comment.
What does the second part of this comment mean? Doesn't Bazel have calls to getStrategies(Spawn, EventHandler)?
There was a problem hiding this comment.
🤦 I got the wrong method signature.
getStrategies(ActionExecutionMetadata, String, EventHandler) is the one only used in Blaze (#22925 (comment)).
Good catch!
| } | ||
|
|
||
| ImmutableListMultimap.Builder<Label, SpawnStrategy> platformToStrategies = ImmutableListMultimap.builder(); | ||
| for (Map.Entry<Label, List<String>> entry : execPlatformFilters.entrySet()) { |
There was a problem hiding this comment.
FWIW I generally think we should always used LinkedHashMap unless there's some known performance / resource risk to doing so.
ce39c90 to
14019a4
Compare
14019a4 to
d88b5e5
Compare
|
Some internal tests are failing and blocking merging. I'll look into them and report back: keeping Bazel 9 cutoff timelines in mind. |
Internal PR adjusted and now in the merge queue. Had to:
Also applied a few code lints and BUILD dependency cleanups. This'll get merged as soon as we get internal approvals. |
| * platform or all if no restrictions are in place. | ||
| * Order from {@code candidateStrategies} is preserved. | ||
| */ | ||
| public <T extends SpawnStrategy> List<T> getStrategies( |
There was a problem hiding this comment.
Forwarding a comment on the internal PR:
"Do we really need this overload? Can we just fix call sites so that they deal in immutable values?"
I take no personal position on this but WDYT?
I responded that I'll forward the comment but merge in the meantime to get into Bazel 9.0. Merge is currently processing...
There was a problem hiding this comment.
No personal position beyond such a refactor being too much for this PR. Similar to https://github.com/bazelbuild/bazel/pull/24265/files/d88b5e5a1fcc4e94ca38cd5dc0758df66228550b#r2545460338.
There was a problem hiding this comment.
Addressing in #27975 (mostly, ImmutableList is a subclass of List so changes are largely within SpawnStrategyRegistry.java).
This PR implements part of the [Execution Platform Scoped Spawn Strategies](https://github.com/bazelbuild/proposals/blob/2b717b19fe805c405576c4feb9ffc6b772068898/designs/2023-06-04-exec-platform-scoped-spawn-strategies.md) proposal. It adds a new flag `--allowed_strategies_by_exec_platform` which permits filtering spawn strategies for spawns execution platform. ## Example ```ini # //.bazelrc # Default strategies (order sensitive) build --spawn_strategy=remote,worker,sandboxed,local # Mnemonic targeted strategy override (order sensitive) build --strategy=BAR=remote,sandboxed # Host platform allowed strategies build --allowed_strategies_by_exec_platform=@platforms//host:host=local,sandboxed,worker # Remote platform allowed strategies build --allowed_strategies_by_exec_platform=//:remote_platform=remote ``` For an action with mnemonic `FOO` configured for the host platform (`@platforms//host:host`), it will resolve `worker,sandboxed,local` as it's spawn strategy candidates. * `remote` was eliminated as a candidate (not in allow list for platform). * Order from `--spawn_strategy` was preserved. For an action with mnemonic `BAR` configured for the host platform (`@platforms//host:host`), it will resolve `sandboxed` as it's spawn strategy candidate. * `remote` was eliminated as a candidate (not in allow list for platform). * Mnemonic override applied, leaving `sandboxed` as the final candidate. For an action with mnemonic `BAR` configured for the remote platform (`//:remote_platform`), it will resolve `remote` as it's spawn strategy candidate. * `sandboxed` was eliminated as a candidate (not in allow list for platform). * Mnemonic override applied, leaving `remote` as the final candidate. If no spawn strategy candidate remains after filtering, the standard error will be logged. ``` ERROR: /workspaces/___/BUILD.bazel:3:22: _description_ [for tool] failed: _mnemonic_ spawn \ cannot be executed with any of the available strategies: []. Your --spawn_strategy, \ --genrule_strategy, --strategy and/or --allowed_strategies_by_exec_platform flags are probably \ too strict. Visit bazelbuild#7480 for advice ``` Closes bazelbuild#24265. PiperOrigin-RevId: 842893103 Change-Id: If2bdb19f08e5dd3c5941f4cfd6c39d7295ff0c25
This PR implements part of the [Execution Platform Scoped Spawn Strategies](https://github.com/bazelbuild/proposals/blob/2b717b19fe805c405576c4feb9ffc6b772068898/designs/2023-06-04-exec-platform-scoped-spawn-strategies.md) proposal. It adds a new flag `--allowed_strategies_by_exec_platform` which permits filtering spawn strategies for spawns execution platform. ## Example ```ini # //.bazelrc # Default strategies (order sensitive) build --spawn_strategy=remote,worker,sandboxed,local # Mnemonic targeted strategy override (order sensitive) build --strategy=BAR=remote,sandboxed # Host platform allowed strategies build --allowed_strategies_by_exec_platform=@platforms//host:host=local,sandboxed,worker # Remote platform allowed strategies build --allowed_strategies_by_exec_platform=//:remote_platform=remote ``` For an action with mnemonic `FOO` configured for the host platform (`@platforms//host:host`), it will resolve `worker,sandboxed,local` as it's spawn strategy candidates. * `remote` was eliminated as a candidate (not in allow list for platform). * Order from `--spawn_strategy` was preserved. For an action with mnemonic `BAR` configured for the host platform (`@platforms//host:host`), it will resolve `sandboxed` as it's spawn strategy candidate. * `remote` was eliminated as a candidate (not in allow list for platform). * Mnemonic override applied, leaving `sandboxed` as the final candidate. For an action with mnemonic `BAR` configured for the remote platform (`//:remote_platform`), it will resolve `remote` as it's spawn strategy candidate. * `sandboxed` was eliminated as a candidate (not in allow list for platform). * Mnemonic override applied, leaving `remote` as the final candidate. If no spawn strategy candidate remains after filtering, the standard error will be logged. ``` ERROR: /workspaces/___/BUILD.bazel:3:22: _description_ [for tool] failed: _mnemonic_ spawn \ cannot be executed with any of the available strategies: []. Your --spawn_strategy, \ --genrule_strategy, --strategy and/or --allowed_strategies_by_exec_platform flags are probably \ too strict. Visit bazelbuild#7480 for advice ``` Closes bazelbuild#24265. PiperOrigin-RevId: 842893103 Change-Id: If2bdb19f08e5dd3c5941f4cfd6c39d7295ff0c25
This PR implements part of the Execution Platform Scoped Spawn Strategies proposal.
It adds a new flag
--allowed_strategies_by_exec_platformwhich permits filtering spawn strategies for spawns execution platform.Example
For an action with mnemonic
FOOconfigured for the host platform (@platforms//host:host), it will resolveworker,sandboxed,localas it's spawn strategy candidates.remotewas eliminated as a candidate (not in allow list for platform).--spawn_strategywas preserved.For an action with mnemonic
BARconfigured for the host platform (@platforms//host:host), it will resolvesandboxedas it's spawn strategy candidate.remotewas eliminated as a candidate (not in allow list for platform).sandboxedas the final candidate.For an action with mnemonic
BARconfigured for the remote platform (//:remote_platform), it will resolveremoteas it's spawn strategy candidate.sandboxedwas eliminated as a candidate (not in allow list for platform).remoteas the final candidate.If no spawn strategy candidate remains after filtering, the standard error will be logged.