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

Make dead code check a query. #93466

Merged
merged 1 commit into from
Feb 2, 2022
Merged

Make dead code check a query. #93466

merged 1 commit into from
Feb 2, 2022

Conversation

cjgillot
Copy link
Contributor

@cjgillot cjgillot commented Jan 29, 2022

Dead code check is run for each invocation of the compiler, even if no modifications were involved.
This PR makes dead code check a query keyed on the module. This allows to skip the check when a module has not changed.
To perform this, a query live_symbols_and_ignored_derived_traits is introduced to encapsulate the global analysis of finding live symbols. The second query check_mod_deathness outputs diagnostics for each module based on this first query's results.

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jan 29, 2022
@rust-highfive
Copy link
Collaborator

r? @nagisa

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 29, 2022
@rust-log-analyzer

This comment has been minimized.

@cjgillot
Copy link
Contributor Author

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jan 30, 2022
@bors
Copy link
Contributor

bors commented Jan 30, 2022

⌛ Trying commit d5edd89788d774568e72164be10a85003618e085 with merge 8d9357a1dbad121b8b946ee45f26ec538118ca50...

@bors
Copy link
Contributor

bors commented Jan 30, 2022

☀️ Try build successful - checks-actions
Build commit: 8d9357a1dbad121b8b946ee45f26ec538118ca50 (8d9357a1dbad121b8b946ee45f26ec538118ca50)

@rust-timer
Copy link
Collaborator

Queued 8d9357a1dbad121b8b946ee45f26ec538118ca50 with parent a00e130, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (8d9357a1dbad121b8b946ee45f26ec538118ca50): comparison url.

Summary: This benchmark run shows 69 relevant improvements 🎉 but 19 relevant regressions 😿 to instruction counts.

  • Average relevant regression: 0.9%
  • Average relevant improvement: -0.8%
  • Largest improvement in instruction counts: -3.1% on incr-unchanged builds of match-stress-enum check
  • Largest regression in instruction counts: 1.5% on incr-patched: dummy fn builds of unused-warnings check

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR led to changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf +perf-regression

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Jan 30, 2022
@nagisa
Copy link
Member

nagisa commented Jan 30, 2022

Could you please add a description to the PR and the commit describing the motivation behind this change (i.e. why is this change being made)?

@cjgillot
Copy link
Contributor Author

@nagisa added one.

Copy link
Member

@nagisa nagisa left a comment

Choose a reason for hiding this comment

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

LGTM overall. r=me with the two suggestions applied.

@@ -999,7 +999,11 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
tcx.ensure().check_private_in_public(());
},
{
sess.time("death_checking", || rustc_passes::dead::check_crate(tcx));
sess.time("death_checking", || {
tcx.hir().par_for_each_module(|module| {
Copy link
Member

@nagisa nagisa Jan 30, 2022

Choose a reason for hiding this comment

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

This par_ has no effect right now because we don't build with parallel_compiler, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. When we are not in parallel_compiler, for_each_module and par_for_each_module are actually the same code.

compiler/rustc_middle/src/query/mod.rs Outdated Show resolved Hide resolved
compiler/rustc_passes/src/dead.rs Outdated Show resolved Hide resolved
@@ -726,6 +728,9 @@ impl<'tcx> Visitor<'tcx> for DeadVisitor<'tcx> {
}

fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
if let hir::ItemKind::Mod(..) = item.kind {
Copy link
Member

Choose a reason for hiding this comment

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

Hm, this looks slightly awkward to me. I wonder if it wouldn't be slightly more straightforward if visit_mod was overriden to be empty and then call walk_mod(visitor, module, module_id) when entering the visitor in check_mod_deathness?

That said, no strong opinion. Feel free to ignore, if you current approach is better.

@nagisa
Copy link
Member

nagisa commented Jan 30, 2022

Hm, as for the perf results, it seems like the improvements are almost universally for the incr-unchanged case (naturally), and all the regressions come from incr-changed ones. From the looks of it, the additional cost may be in serializing the query results or some similar query system overhead (for e.g. here just the query to compute live items takes as much time as the death_checking did before on its own). I'm not familiar with the query system enough to suggest if there's a good way to avoid this…

@rust-log-analyzer

This comment has been minimized.

@nagisa
Copy link
Member

nagisa commented Jan 30, 2022

@cjgillot will you be looking into the perf regressions? I would not necessarily consider them hard blockers to landing this PR, but having a well researched description (since mine above is broadly just a guess) of why the perf hit is occurring in the first place would be nice.

@bors try @rust-timer queue

(not expecting significant changes in results, but the structure of the change will change the output of the timings somewhat and its better to be looking at the “current” version)

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jan 30, 2022
@bors
Copy link
Contributor

bors commented Jan 30, 2022

⌛ Trying commit 2c388378967e0ae6acbae938354c3e5d3f8e6c40 with merge 0c4e6240c88e78143766255d9e71641b59b94632...

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@bors
Copy link
Contributor

bors commented Jan 31, 2022

☀️ Try build successful - checks-actions
Build commit: 0c4e6240c88e78143766255d9e71641b59b94632 (0c4e6240c88e78143766255d9e71641b59b94632)

@rust-timer
Copy link
Collaborator

Queued 0c4e6240c88e78143766255d9e71641b59b94632 with parent 8c7f2bf, future comparison URL.

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jan 31, 2022
@cjgillot
Copy link
Contributor Author

The logic itself is not changed, so I lean towards query overhead.

Without digging very deep in the perf results:

  • the regression only appear for some incr-full and incr-patched loads : full is neutral, incr-unchanged is green;
  • the time taken by live_symbols_and_ignored_derived_traits + check_mod_deathness is of the same order of magnitude as former death_checking.

My guess is query system overhead: result hashing and dependency bookkeeping are responsible for the regression. Both are possible (live_symbols return value may be sizeable, and the former implementation did not keep a log of dependencies).

@nagisa
Copy link
Member

nagisa commented Jan 31, 2022

I just realised what could be the at least partially the cause.

query live_symbols_and_ignored_derived_traits(_: ()) -> (FxHashSet<_>, FxHashMap<_, _>

to the best of my knowledge means that every time tcx.live_symbols_and_ignored_derived_traits() is called, its cached result will be cloned to produce an owned value result.

The check_mod_deathness then invokes this query for every module, thus resulting in N clones of the somewhat sizable list live symbols.

I wonder if storing the live symbols into TyCtxt and returning a &'tcx FxHash{Set,Map} would help to get rid of the regression.

@cjgillot
Copy link
Contributor Author

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jan 31, 2022
@bors
Copy link
Contributor

bors commented Jan 31, 2022

⌛ Trying commit b615df8d38887490c1b5955a654bd768ccbf9086 with merge fe3d394eec18b66eb89c81e6048e3bb4480c71b5...

@bors
Copy link
Contributor

bors commented Jan 31, 2022

☀️ Try build successful - checks-actions
Build commit: fe3d394eec18b66eb89c81e6048e3bb4480c71b5 (fe3d394eec18b66eb89c81e6048e3bb4480c71b5)

@rust-timer
Copy link
Collaborator

Queued fe3d394eec18b66eb89c81e6048e3bb4480c71b5 with parent 86f5e17, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (fe3d394eec18b66eb89c81e6048e3bb4480c71b5): comparison url.

Summary: This benchmark run shows 67 relevant improvements 🎉 but 8 relevant regressions 😿 to instruction counts.

  • Average relevant regression: 1.0%
  • Average relevant improvement: -0.8%
  • Largest improvement in instruction counts: -3.3% on incr-unchanged builds of match-stress-enum check
  • Largest regression in instruction counts: 1.5% on incr-patched: dummy fn builds of unused-warnings check

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR led to changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf +perf-regression

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jan 31, 2022
@nagisa
Copy link
Member

nagisa commented Feb 1, 2022

Looks great now. r=me with a cleaned up history.

@cjgillot
Copy link
Contributor Author

cjgillot commented Feb 1, 2022

@bors r=nagisa

@bors
Copy link
Contributor

bors commented Feb 1, 2022

📌 Commit 4e7d47b has been approved by nagisa

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 1, 2022
@bors
Copy link
Contributor

bors commented Feb 2, 2022

⌛ Testing commit 4e7d47b with merge d5f9c40...

@bors
Copy link
Contributor

bors commented Feb 2, 2022

☀️ Test successful - checks-actions
Approved by: nagisa
Pushing d5f9c40 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Feb 2, 2022
@bors bors merged commit d5f9c40 into rust-lang:master Feb 2, 2022
@rustbot rustbot added this to the 1.60.0 milestone Feb 2, 2022
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (d5f9c40): comparison url.

Summary: This benchmark run shows 69 relevant improvements 🎉 but 12 relevant regressions 😿 to instruction counts.

  • Average relevant regression: 0.9%
  • Average relevant improvement: -0.8%
  • Largest improvement in instruction counts: -3.1% on incr-unchanged builds of match-stress-enum check
  • Largest regression in instruction counts: 1.6% on incr-patched: dummy fn builds of unused-warnings check

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

Next Steps: If you can justify the regressions found in this perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please open an issue or create a new PR that fixes the regressions, add a comment linking to the newly created issue or PR, and then add the perf-regression-triaged label to this PR.

@rustbot label: +perf-regression

@Zoxc
Copy link
Contributor

Zoxc commented Feb 3, 2022

This PR does seem to regress, in instruction counts, both incr-full and incr-patched, which makes sense given that dead code checking runs on the entire crate and you can't easily offset the query overhead by skipping parts of its computation. It does help incr-unchanged, but that isn't a realistic workload and it shouldn't be prioritized over incr-patched.

@nagisa
Copy link
Member

nagisa commented Feb 3, 2022

that isn't a realistic workload

Is it, really? Wouldn't running cargo test after the IDE cargo checks the crate for inline diagnostics be an example of a recurrent incr-unchanged workload?

@Zoxc
Copy link
Contributor

Zoxc commented Feb 3, 2022

Switching between cargo check and cargo build using the same incremental directory might be considered unmodified. cargo test adds tests and implicitly imports the test crate so I don't think it would qualify.

cargo check, cargo build and cargo test have separate incremental directories, so from the perspective of the incremental system there's no mixing of commands, which is mostly a good thing, since it only keeps computations from the latest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. perf-regression Performance regression. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants