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

Encode spans relative to the enclosing item #84373

Merged
merged 12 commits into from
Sep 12, 2021
Merged

Conversation

cjgillot
Copy link
Contributor

@cjgillot cjgillot commented Apr 20, 2021

The aim of this PR is to avoid recomputing queries when code is moved without modification.

MCP at rust-lang/compiler-team#443

This is achieved by :

  1. storing the HIR owner LocalDefId information inside the span;
  2. encoding and decoding spans relative to the enclosing item in the incremental on-disk cache;
  3. marking a dependency to the source_span(LocalDefId) query when we translate a span from the short (Span) representation to its explicit (SpanData) representation.

Since all client code uses Span, step 3 ensures that all manipulations
of span byte positions actually create the dependency edge between
the caller and the source_span(LocalDefId).
This query return the actual absolute span of the parent item.
As a consequence, any source code motion that changes the absolute byte position of a node will either:

  • modify the distance to the parent's beginning, so change the relative span's hash;
  • dirty source_span, and trigger the incremental recomputation of all code that
    depends on the span's absolute byte position.

With this scheme, I believe the dependency tracking to be accurate.

For the moment, the spans are marked during lowering.
I'd rather do this during def-collection,
but the AST MutVisitor is not practical enough just yet.
The only difference is that we attach macro-expanded spans
to their expansion point instead of the macro itself.

@rust-log-analyzer

This comment has been minimized.

@petrochenkov
Copy link
Contributor

I don't like the idea of keeping the ID in SpanData and would like to see a separate type for this, like LoweredSpan.
I see why it was faster to prototype this with a single Span type though.

@jyn514 jyn514 added A-incr-comp Area: Incremental compilation T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. I-compiletime Issue: Problems and improvements with respect to compile times. labels Apr 20, 2021
@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 Apr 24, 2021
@bors
Copy link
Contributor

bors commented Apr 24, 2021

⌛ Trying commit d861775a3095b6bc7b23e4dc2acfb30a82f104c2 with merge 53c860c88de8437287861ee8c26eaedbe95dd7fb...

@rust-log-analyzer

This comment has been minimized.

@cjgillot
Copy link
Contributor Author

I don't like the idea of keeping the ID in SpanData and would like to see a separate type for this, like LoweredSpan.
I see why it was faster to prototype this with a single Span type though.

On the one hand, I agree with you, putting the ID in the SpanData is a bad hack, and invites silent invalidations.
On the other hand, I would like to assign the stable spans in the AST, to make macro-expanded spans relative to the enclosing macro.

I shall think a bit more about it. Creating a hir::Span and putting it everywhere is probably the most robust option.

@bors
Copy link
Contributor

bors commented Apr 24, 2021

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

@rust-timer
Copy link
Collaborator

Queued 53c860c88de8437287861ee8c26eaedbe95dd7fb with parent 2b68027, future comparison URL.

@rust-log-analyzer

This comment has been minimized.

@rust-timer

This comment has been minimized.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Apr 24, 2021
@cjgillot
Copy link
Contributor Author

perf report : bad (I mean don't look, its really bad).
I think I've been too heavy handed in querifying source_map, which pessimizes MIR and CGU reuse.

@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

@rust-log-analyzer

This comment has been minimized.

@cjgillot
Copy link
Contributor Author

@bors r=michaelwoerister,petrochenkov

About the perf regression: this PR implements an opt-in feature to reduce span-related recomputations for incr-comp. Measurements in #84762 show up to -25% instruction reduction when enabled. When disabled, the perf hit appears to be a consistent 1-2% instruction hit.

@bors
Copy link
Contributor

bors commented Sep 11, 2021

📌 Commit 7842b80 has been approved by michaelwoerister,petrochenkov

@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 Sep 11, 2021
@bors
Copy link
Contributor

bors commented Sep 11, 2021

⌛ Testing commit 7842b80 with merge 547d937...

@bors
Copy link
Contributor

bors commented Sep 12, 2021

☀️ Test successful - checks-actions
Approved by: michaelwoerister,petrochenkov
Pushing 547d937 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Sep 12, 2021
@bors bors merged commit 547d937 into rust-lang:master Sep 12, 2021
@rustbot rustbot added this to the 1.57.0 milestone Sep 12, 2021
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (547d937): comparison url.

Summary: This change led to large relevant regressions 😿 in compiler performance.

  • Large regression in instruction counts (up to 2.1% on incr-unchanged builds of tuple-stress)

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

@cjgillot cjgillot deleted the resolve-span branch September 12, 2021 11:39
flip1995 pushed a commit to flip1995/rust that referenced this pull request Sep 28, 2021
…ster,petrochenkov

Encode spans relative to the enclosing item

The aim of this PR is to avoid recomputing queries when code is moved without modification.

MCP at rust-lang/compiler-team#443

This is achieved by :
1. storing the HIR owner LocalDefId information inside the span;
2. encoding and decoding spans relative to the enclosing item in the incremental on-disk cache;
3. marking a dependency to the `source_span(LocalDefId)` query when we translate a span from the short (`Span`) representation to its explicit (`SpanData`) representation.

Since all client code uses `Span`, step 3 ensures that all manipulations
of span byte positions actually create the dependency edge between
the caller and the `source_span(LocalDefId)`.
This query return the actual absolute span of the parent item.
As a consequence, any source code motion that changes the absolute byte position of a node will either:
- modify the distance to the parent's beginning, so change the relative span's hash;
- dirty `source_span`, and trigger the incremental recomputation of all code that
  depends on the span's absolute byte position.

With this scheme, I believe the dependency tracking to be accurate.

For the moment, the spans are marked during lowering.
I'd rather do this during def-collection,
but the AST MutVisitor is not practical enough just yet.
The only difference is that we attach macro-expanded spans
to their expansion point instead of the macro itself.
@Mark-Simulacrum
Copy link
Member

About the perf regression: this PR implements an opt-in feature to reduce span-related recomputations for incr-comp. Measurements in #84762 show up to -25% instruction reduction when enabled. When disabled, the perf hit appears to be a consistent 1-2% instruction hit.

So seems justified and action on this PR not expected.

@Mark-Simulacrum Mark-Simulacrum added the perf-regression-triaged The performance regression has been triaged. label Oct 3, 2021
JohnTitor added a commit to JohnTitor/rust-semverver that referenced this pull request Oct 15, 2021
calebcartwright pushed a commit to calebcartwright/rust that referenced this pull request Oct 20, 2021
…ster,petrochenkov

Encode spans relative to the enclosing item

The aim of this PR is to avoid recomputing queries when code is moved without modification.

MCP at rust-lang/compiler-team#443

This is achieved by :
1. storing the HIR owner LocalDefId information inside the span;
2. encoding and decoding spans relative to the enclosing item in the incremental on-disk cache;
3. marking a dependency to the `source_span(LocalDefId)` query when we translate a span from the short (`Span`) representation to its explicit (`SpanData`) representation.

Since all client code uses `Span`, step 3 ensures that all manipulations
of span byte positions actually create the dependency edge between
the caller and the `source_span(LocalDefId)`.
This query return the actual absolute span of the parent item.
As a consequence, any source code motion that changes the absolute byte position of a node will either:
- modify the distance to the parent's beginning, so change the relative span's hash;
- dirty `source_span`, and trigger the incremental recomputation of all code that
  depends on the span's absolute byte position.

With this scheme, I believe the dependency tracking to be accurate.

For the moment, the spans are marked during lowering.
I'd rather do this during def-collection,
but the AST MutVisitor is not practical enough just yet.
The only difference is that we attach macro-expanded spans
to their expansion point instead of the macro itself.
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 2, 2023
…nkov

Encode spans relative to the enclosing item -- enable on nightly

Follow-up to rust-lang#84373 with the flag `-Zincremental-relative-spans` set by default.

This PR seeks to remove one of the main shortcomings of incremental: the handling of spans.
Changing the contents of a function may require redoing part of the compilation process for another function in another file because of span information is changed.
Within one file: all the spans in HIR change, so typechecking had to be re-done.
Between files: spans of associated types/consts/functions change, so type-based resolution needs to be re-done (hygiene information is stored in the span).

The flag `-Zincremental-relative-spans` encodes local spans relative to the span of an item, stored inside the `source_span` query.

Trap: stashed diagnostics are referenced by the "raw" span, so stealing them requires to remove the span's parent.

In order to avoid too much traffic in the span interner, span encoding uses the `ctxt_or_tag` field to encode:
- the parent when the `SyntaxContext` is 0;
- the `SyntaxContext` when the parent is `None`.
Even with this, the PR creates a lot of traffic to the Span interner, when a Span has both a LocalDefId parent and a non-root SyntaxContext. They appear in lowering, when we add a parent to all spans, including those which come from macros, and during inlining when we mark inlined spans.

The last commit changes how queries of `LocalDefId` manage their cache. I can put this in a separate PR if required.

Possible future directions:
- validate that all spans are marked in HIR validation;
- mark macro-expanded spans relative to the def-site and not the use-site.
Aaron1011 pushed a commit to Aaron1011/rust that referenced this pull request Jan 6, 2023
…nkov

Encode spans relative to the enclosing item -- enable on nightly

Follow-up to rust-lang#84373 with the flag `-Zincremental-relative-spans` set by default.

This PR seeks to remove one of the main shortcomings of incremental: the handling of spans.
Changing the contents of a function may require redoing part of the compilation process for another function in another file because of span information is changed.
Within one file: all the spans in HIR change, so typechecking had to be re-done.
Between files: spans of associated types/consts/functions change, so type-based resolution needs to be re-done (hygiene information is stored in the span).

The flag `-Zincremental-relative-spans` encodes local spans relative to the span of an item, stored inside the `source_span` query.

Trap: stashed diagnostics are referenced by the "raw" span, so stealing them requires to remove the span's parent.

In order to avoid too much traffic in the span interner, span encoding uses the `ctxt_or_tag` field to encode:
- the parent when the `SyntaxContext` is 0;
- the `SyntaxContext` when the parent is `None`.
Even with this, the PR creates a lot of traffic to the Span interner, when a Span has both a LocalDefId parent and a non-root SyntaxContext. They appear in lowering, when we add a parent to all spans, including those which come from macros, and during inlining when we mark inlined spans.

The last commit changes how queries of `LocalDefId` manage their cache. I can put this in a separate PR if required.

Possible future directions:
- validate that all spans are marked in HIR validation;
- mark macro-expanded spans relative to the def-site and not the use-site.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-incr-comp Area: Incremental compilation I-compiletime Issue: Problems and improvements with respect to compile times. merged-by-bors This PR was explicitly merged by bors. perf-regression Performance regression. perf-regression-triaged The performance regression has been triaged. 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. WG-incr-comp Working group: Incremental compilation
Projects
None yet
Development

Successfully merging this pull request may close these issues.