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

Speed up Parser::expected_tokens #133793

Merged
merged 6 commits into from
Dec 19, 2024

Conversation

nnethercote
Copy link
Contributor

@nnethercote nnethercote commented Dec 3, 2024

The constant pushing/clearing of Parser::expected_tokens during parsing is slow. This PR speeds it up greatly.

r? @estebank

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Dec 3, 2024
@nnethercote
Copy link
Contributor Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Dec 3, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 3, 2024
…, r=<try>

Speed up `Parser::expected_tokens`

r? `@ghost`
@bors
Copy link
Contributor

bors commented Dec 3, 2024

⌛ Trying commit 0133601 with merge 4e6952e...

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Dec 3, 2024

☀️ Try build successful - checks-actions
Build commit: 4e6952e (4e6952e2fa4367d9a5ef87505fa18f0dd3fedcc4)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (4e6952e): comparison URL.

Overall result: ✅ improvements - no action needed

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 may lead to changes in compiler perf.

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

Instruction count

This is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.9% [-2.4%, -0.2%] 211
Improvements ✅
(secondary)
-0.8% [-2.6%, -0.1%] 101
All ❌✅ (primary) -0.9% [-2.4%, -0.2%] 211

Max RSS (memory usage)

Results (primary -1.2%, secondary 1.6%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
0.5% [0.5%, 0.5%] 1
Regressions ❌
(secondary)
2.9% [0.9%, 5.4%] 3
Improvements ✅
(primary)
-2.1% [-2.3%, -1.8%] 2
Improvements ✅
(secondary)
-2.2% [-2.2%, -2.2%] 1
All ❌✅ (primary) -1.2% [-2.3%, 0.5%] 3

Cycles

Results (primary -1.5%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.5% [-1.5%, -1.5%] 2
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -1.5% [-1.5%, -1.5%] 2

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 767.333s -> 766.554s (-0.10%)
Artifact size: 332.08 MiB -> 332.14 MiB (0.02%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Dec 3, 2024
@nnethercote nnethercote force-pushed the speed-up-expected_tokens branch from 0133601 to f5482df Compare December 4, 2024 05:40
@nnethercote nnethercote marked this pull request as ready for review December 4, 2024 05:40
@rustbot
Copy link
Collaborator

rustbot commented Dec 4, 2024

Some changes occurred in src/tools/rustfmt

cc @rust-lang/rustfmt

@nnethercote
Copy link
Contributor Author

Best reviewed one commit at a time.

Let's re-run perf just to be sure: @bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Dec 4, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 4, 2024
…, r=<try>

Speed up `Parser::expected_tokens`

The constant pushing/clearing of `Parser::expected_tokens` during parsing is slow. This PR speeds it up greatly.

r? `@estebank`
@bors
Copy link
Contributor

bors commented Dec 4, 2024

⌛ Trying commit f5482df with merge 26060e6...

Comment on lines 16 to 17
/// We really want to keep the number of variants to 128 or fewer, sot that
/// `TokenTypeSet` can be implemented with a `u128`.
Copy link
Contributor

Choose a reason for hiding this comment

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

On the one hand, we should be able to do so. On the other, I can see this becoming a point of contention with t-lang in the medium future if we push back on a feature for this reason :)

Copy link
Contributor Author

@nnethercote nnethercote Dec 4, 2024

Choose a reason for hiding this comment

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

The 17 asm symbols would be a good place to cut things down if necessary. I'm a bit annoyed that they are even in there; so many of them for such a rare use case.

Comment on lines 264 to 277
// This assertion will detect if this method and the type definition get out of sync.
assert_eq!(token_type as u32, val);
token_type
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't the function just be the as cast with a <=104 check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No. You can convert a C-style enum to an integer with as, but you can't convert in the other direction, e.g. as per this StackOverflow answer. There are proc macros to do it, but that answer pointed out an alternative that is suitable here: transmute is fine so long as the enum is repr(uN) for some value of N. So I will do that with repr(u8), which will cut over 100 lines of code, yay.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we have a static assertion that all of them roundtrip? I'm always concerned about a careless future reformat breaking the bidirectional mapping.

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'd be happy for extra protection, but I'm having trouble imagining what such a static assertion would look like. Can you explain more?

Copy link
Contributor Author

@nnethercote nnethercote Dec 5, 2024

Choose a reason for hiding this comment

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

Alternatively, I can go back to an explicit match. The StackOverflow answer mentioned this style:

match v {
    x if x == MyEnum::A as i32 => Ok(MyEnum::A),
    x if x == MyEnum::B as i32 => Ok(MyEnum::B),
    x if x == MyEnum::C as i32 => Ok(MyEnum::C),
    _ => Err(()),
}

It requires a line for every variant, but avoids having to write a number on each line.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd be happy for extra protection, but I'm having trouble imagining what such a static assertion would look like. Can you explain more?

I'd forgotten that the range operation doesn't work today in const, but I was picturing something like:

const __CHECK: () = const {
    for i in 0..2 {
        assert_eq!(E::to_i32(&E::from_i32(i)), i);
    }
};

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've gone with the guard-based version, using a macro to avoid excessive boilerplate. It doesn't rely on unsafe, and also doesn't rely on matching up the right integer with the right variant.

@estebank
Copy link
Contributor

estebank commented Dec 4, 2024

I'll finish reviewing tomorrow

@bors
Copy link
Contributor

bors commented Dec 4, 2024

☀️ Try build successful - checks-actions
Build commit: 26060e6 (26060e63f06a4dcd55fc0757eb5b0bdc8136ed3b)

@rust-timer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Dec 19, 2024

☀️ Try build successful - checks-actions
Build commit: 7ebe629 (7ebe629a8d2d74c9bf12e339350633096488d6ae)

@nnethercote
Copy link
Contributor Author

@bors r=spastorino

@bors
Copy link
Contributor

bors commented Dec 19, 2024

📌 Commit 0f7dccf has been approved by spastorino

It is now in the queue for this repository.

@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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 19, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 19, 2024
…, r=spastorino

Speed up `Parser::expected_tokens`

The constant pushing/clearing of `Parser::expected_tokens` during parsing is slow. This PR speeds it up greatly.

r? `@estebank`
@bors
Copy link
Contributor

bors commented Dec 19, 2024

⌛ Testing commit 0f7dccf with merge 9c6d84c...

@jieyouxu
Copy link
Member

Some try jobs are not getting picked up correctly, trying a sync cc https://rust-lang.zulipchat.com/#narrow/channel/242791-t-infra/topic/try.20jobs.20not.20kicking.20off.
@bors treeclosed=1000

@jieyouxu
Copy link
Member

@bors r- retry (sync)

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 19, 2024
@nnethercote
Copy link
Contributor Author

The tree seems to be back open?

@bors r=spastorino

@bors
Copy link
Contributor

bors commented Dec 19, 2024

📌 Commit 0f7dccf has been approved by spastorino

It is now in the queue for this repository.

@bors
Copy link
Contributor

bors commented Dec 19, 2024

⌛ Testing commit 0f7dccf with merge 9e136a3...

@jieyouxu
Copy link
Member

Oops yeah, sorry about that -- bors picked up treeclosed from another PR, and I lost track of this PR due to notifications flood...

@bors
Copy link
Contributor

bors commented Dec 19, 2024

☀️ Test successful - checks-actions
Approved by: spastorino
Pushing 9e136a3 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Dec 19, 2024
@bors bors merged commit 9e136a3 into rust-lang:master Dec 19, 2024
7 checks passed
@rustbot rustbot added this to the 1.85.0 milestone Dec 19, 2024
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (9e136a3): comparison URL.

Overall result: ✅ improvements - no action needed

@rustbot label: -perf-regression

Instruction count

This is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-0.9% [-2.5%, -0.2%] 213
Improvements ✅
(secondary)
-0.8% [-2.5%, -0.1%] 105
All ❌✅ (primary) -0.9% [-2.5%, -0.2%] 213

Max RSS (memory usage)

Results (primary -0.1%, secondary -0.9%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
2.0% [2.0%, 2.1%] 2
Regressions ❌
(secondary)
4.8% [4.8%, 4.8%] 1
Improvements ✅
(primary)
-1.5% [-2.1%, -0.9%] 3
Improvements ✅
(secondary)
-2.4% [-3.7%, -1.8%] 4
All ❌✅ (primary) -0.1% [-2.1%, 2.1%] 5

Cycles

Results (primary -1.2%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.2% [-1.7%, -1.0%] 4
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -1.2% [-1.7%, -1.0%] 4

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 769.451s -> 766.727s (-0.35%)
Artifact size: 330.39 MiB -> 330.36 MiB (-0.01%)

@nnethercote nnethercote deleted the speed-up-expected_tokens branch December 20, 2024 04:19
@cuviper
Copy link
Member

cuviper commented Jan 22, 2025

The job dist-s390x-linux failed! Check out the build log: (web) (plain)
Click to see the possible cause of the failure (guessed by this bot)

   Compiling rustc_parse v0.0.0 (/checkout/compiler/rustc_parse)
error[E0308]: mismatched types
   --> /rustc/e46b2c453cbcb2f95ccc20904d6944711c1c9aa4/compiler/rustc_index/src/lib.rs:40:32
    |
38  | macro_rules! static_assert_size {
    | ------------------------------- in this expansion of `rustc_data_structures::static_assert_size!`
39  |     ($ty:ty, $size:expr) => {
40  |         const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a size of 288, found one with a size of 280
   ::: compiler/rustc_parse/src/parser/mod.rs:194:56
    |
    |
194 | rustc_data_structures::static_assert_size!(Parser<'_>, 288);
    | |                                                      |
    | |                                                      help: consider specifying the actual array length: `280`
    | in this macro invocation

s390s size assertion failure, fun.

I just got the same error with 280 on powerpc64le in a Fedora scratch build of 1.85.0-beta.5:
https://kojipkgs.fedoraproject.org//work/tasks/4794/128284794/build.log

I have no idea why it would be different than Rust CI though, which apparently did pass on that arch...

@cuviper
Copy link
Member

cuviper commented Jan 22, 2025

I think the difference is due to the alignment of TokenTypeSet(u128), which is only 8 on ppc64 and s390x... at least until #134115 takes effect on ppc64 with LLVM 20. But again, I don't know why Rust CI didn't see that too!

@cuviper
Copy link
Member

cuviper commented Jan 23, 2025

I have no idea why it would be different than Rust CI though

I figured it out -- #134115 changed ppc64 alignment regardless of LLVM version, but when I'm building natively it's starting with the old alignment in stage0, while Rust CI only cross-compiles using the last stage.

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. 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.

10 participants