Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Force output checking for incremental run commands without the bytes. #20853

Closed
wants to merge 1 commit into from

Conversation

tjgq
Copy link
Contributor

@tjgq tjgq commented Jan 11, 2024

When building without the bytes, outputs are only materialized when either (1) an action prefetches them, or (2) they've been explicitly requested. When both --remote_download_minimal and --noexperimental_check_output_files are set, this presents a problem for a build command followed by a run command for the same target: the build command won't download the outputs and the run command won't check for their presence, proceeding without them. A non-incremental run command works, because the outputs are considered top-level even in minimal mode.

This is only a problem for a run command because it exists outside of action execution, and doesn't get a chance to prefetch inputs; it would have been better to implement the run command by injecting a specially crafted action into the build graph, but that will have to wait for another day. The present fix might theoretically slow things down if output checking is truly unnecessary, but I doubt that would cause a significant regression in practice.

Fixes #20843.

@tjgq tjgq requested a review from a team as a code owner January 11, 2024 15:48
@tjgq tjgq force-pushed the checkoutputs-bwob branch 2 times, most recently from 0e4f0a0 to 7fefaf2 Compare January 11, 2024 15:51
When building without the bytes, outputs are only materialized when either
(1) an action prefetches them, or (2) they've been explicitly requested. When
both --remote_download_minimal and --noexperimental_check_output_files are
set, this presents a problem for a build command followed by a run command
for the same target: the build command won't download the outputs and the run
command won't check for their presence, proceeding without them. A
non-incremental run command works, because the outputs are considered
top-level even in minimal mode.

This is only a problem for a run command because it exists outside of action
execution, and doesn't get a chance to prefetch inputs; it would have been
better to implement the run command by injecting a specially crafted action
into the build graph, but that will have to wait for another day. The present
fix might theoretically slow things down if output checking is truly
unnecessary, but I doubt that would cause a significant regression in
practice.

Fixes bazelbuild#20843.
@tjgq tjgq force-pushed the checkoutputs-bwob branch from 7fefaf2 to 5bc9620 Compare January 11, 2024 16:17
Comment on lines +527 to +528
if (!modifiedOutputFiles.treatEverythingAsDeleted() && !request.getCommandName()
.equals("run")) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I can make the check narrower, because the remote options can change between builds without invalidating the Skyframe state. (But maybe you can see a way.)

@iancha1992 iancha1992 added the team-Remote-Exec Issues and PRs for the Execution (Remote) team label Jan 11, 2024
@coeuvre coeuvre added the awaiting-PR-merge PR has been approved by a reviewer and is ready to be merge internally label Jan 12, 2024
@tjgq
Copy link
Contributor Author

tjgq commented Jan 12, 2024

@bazel-io fork 7.0.1

@github-actions github-actions bot removed the awaiting-PR-merge PR has been approved by a reviewer and is ready to be merge internally label Jan 12, 2024
bazel-io pushed a commit to bazel-io/bazel that referenced this pull request Jan 12, 2024
When building without the bytes, outputs are only materialized when either (1) an action prefetches them, or (2) they've been explicitly requested. When both --remote_download_minimal and --noexperimental_check_output_files are set, this presents a problem for a build command followed by a run command for the same target: the build command won't download the outputs and the run command won't check for their presence, proceeding without them. A non-incremental run command works, because the outputs are considered top-level even in minimal mode.

This is only a problem for a run command because it exists outside of action execution, and doesn't get a chance to prefetch inputs; it would have been better to implement the run command by injecting a specially crafted action into the build graph, but that will have to wait for another day. The present fix might theoretically slow things down if output checking is truly unnecessary, but I doubt that would cause a significant regression in practice.

Fixes bazelbuild#20843.

Closes bazelbuild#20853.

PiperOrigin-RevId: 597909909
Change-Id: I66aedef4994fbda41fe5378c80940fa8ba637bfd
meteorcloudy pushed a commit that referenced this pull request Jan 15, 2024
…e bytes. (#20881)

When building without the bytes, outputs are only materialized when
either (1) an action prefetches them, or (2) they've been explicitly
requested. When both --remote_download_minimal and
--noexperimental_check_output_files are set, this presents a problem for
a build command followed by a run command for the same target: the build
command won't download the outputs and the run command won't check for
their presence, proceeding without them. A non-incremental run command
works, because the outputs are considered top-level even in minimal
mode.

This is only a problem for a run command because it exists outside of
action execution, and doesn't get a chance to prefetch inputs; it would
have been better to implement the run command by injecting a specially
crafted action into the build graph, but that will have to wait for
another day. The present fix might theoretically slow things down if
output checking is truly unnecessary, but I doubt that would cause a
significant regression in practice.

Fixes #20843.

Closes #20853.

Commit
2f899ef

PiperOrigin-RevId: 597909909
Change-Id: I66aedef4994fbda41fe5378c80940fa8ba637bfd

Co-authored-by: Tiago Quelhas <tjgq@google.com>
@iancha1992
Copy link
Member

@bazel-io fork 7.1.0

bazel-io pushed a commit to bazel-io/bazel that referenced this pull request Jan 22, 2024
When building without the bytes, outputs are only materialized when either (1) an action prefetches them, or (2) they've been explicitly requested. When both --remote_download_minimal and --noexperimental_check_output_files are set, this presents a problem for a build command followed by a run command for the same target: the build command won't download the outputs and the run command won't check for their presence, proceeding without them. A non-incremental run command works, because the outputs are considered top-level even in minimal mode.

This is only a problem for a run command because it exists outside of action execution, and doesn't get a chance to prefetch inputs; it would have been better to implement the run command by injecting a specially crafted action into the build graph, but that will have to wait for another day. The present fix might theoretically slow things down if output checking is truly unnecessary, but I doubt that would cause a significant regression in practice.

Fixes bazelbuild#20843.

Closes bazelbuild#20853.

PiperOrigin-RevId: 597909909
Change-Id: I66aedef4994fbda41fe5378c80940fa8ba637bfd
github-merge-queue bot pushed a commit that referenced this pull request Jan 27, 2024
…e bytes. (#20988)

When building without the bytes, outputs are only materialized when
either (1) an action prefetches them, or (2) they've been explicitly
requested. When both --remote_download_minimal and
--noexperimental_check_output_files are set, this presents a problem for
a build command followed by a run command for the same target: the build
command won't download the outputs and the run command won't check for
their presence, proceeding without them. A non-incremental run command
works, because the outputs are considered top-level even in minimal
mode.

This is only a problem for a run command because it exists outside of
action execution, and doesn't get a chance to prefetch inputs; it would
have been better to implement the run command by injecting a specially
crafted action into the build graph, but that will have to wait for
another day. The present fix might theoretically slow things down if
output checking is truly unnecessary, but I doubt that would cause a
significant regression in practice.

Fixes #20843.

Closes #20853.

Commit
2f899ef

PiperOrigin-RevId: 597909909
Change-Id: I66aedef4994fbda41fe5378c80940fa8ba637bfd

Co-authored-by: Tiago Quelhas <tjgq@google.com>
@tjgq tjgq deleted the checkoutputs-bwob branch March 7, 2024 10:36
@tomdegoede
Copy link
Contributor

@tjgq This change slows down our bazel run invocations by 5 seconds compared to bazel build. I think your theoretical case of switching remote options between builds will be very uncommon in practice, where these settings are pinned in the .bazelrc. Could you reconsider narrowing down the check to also return NOTHING_MODIFIED when remote download is set to all? This would allow us to speed up common dev tasks by 5 seconds.

@tjgq
Copy link
Contributor Author

tjgq commented Nov 5, 2024

I think your theoretical case of switching remote options between builds will be very uncommon in practice, where these settings are pinned in the .bazelrc

Switching options is not the problem; the problem is a bazel build followed by a bazel run, even if the output mode hasn't changed. The test case added by this PR demonstrates this.

Could you reconsider narrowing down the check to also return NOTHING_MODIFIED when remote download is set to all? This would allow us to speed up common dev tasks by 5 seconds.

To be absolutely clear, the condition for NOTHING_MODIFIED isn't whether --remote_download_all is set in the current invocation; the condition for a complete fix is whether the previous invocation either set --remote_download_all, or it set --remote_download_toplevel and the bazel run target was toplevel. It can definitely be done, but it requires keeping this additional state somewhere, so it's not a localized fix.

(Switching between output modes might be infrequent, but we don't have the luxury of saying "we'll be correct unless you happen to do something unusual".)

As mentioned in the PR description, there's also the alternative of reimplementing bazel run as a specifically crafted build action, but I think that's more difficult (though more principled).

@tjgq
Copy link
Contributor Author

tjgq commented Nov 5, 2024

To be absolutely clear, the condition for NOTHING_MODIFIED isn't whether --remote_download_all is set in the current invocation; the condition for a complete fix is whether the previous invocation either set --remote_download_all, or it set --remote_download_toplevel and the bazel run target was toplevel. It can definitely be done, but it requires keeping this additional state somewhere, so it's not a localized fix.

It turns out that I'm wrong, and the fix is much simpler than anticipated: the changes in 4c42edb also made this workaround unnecessary, so we can literally revert this PR and fix the performance issue while preserving correctness (if the integration test is to be believed). I'll send it in soon.

@tomdegoede
Copy link
Contributor

Amazing! Thanks @tjgq :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
team-Remote-Exec Issues and PRs for the Execution (Remote) team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incremental bazel run + BwoB + --noexperimental_check_output_files = slow
4 participants