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

Migrate compiler's &Option<T> into Option<&T> #130963

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

nyurik
Copy link
Contributor

@nyurik nyurik commented Sep 28, 2024

Similar to #130962 but for the compiler.

Trying out my new lint rust-lang/rust-clippy#13336 - according to the video, this could lead to some performance and memory optimizations.

Basic thoughts expressed in the video that seem to make sense:

  • &Option<T> in an API breaks encapsulation:
    • caller must own T and move it into an Option to call with it
    • if returned, the owner must store it as Option internally in order to return it
  • Performance is subject to compiler optimization, but at the basics, &Option<T> points to memory that has presence flag + value, whereas Option<&T> by specification is always optimized to a single pointer.

@rustbot
Copy link
Collaborator

rustbot commented Sep 28, 2024

r? @petrochenkov

rustbot has assigned @petrochenkov.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) 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 Sep 28, 2024
@rustbot
Copy link
Collaborator

rustbot commented Sep 28, 2024

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

@nyurik nyurik changed the title Change a few &Option<T> into Option<&T> Migrate compiler's &Option<T> into Option<&T> Sep 28, 2024
@workingjubilee
Copy link
Member

@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 Sep 28, 2024
@rust-log-analyzer

This comment has been minimized.

bors added a commit to rust-lang-ci/rust that referenced this pull request Sep 28, 2024
Migrate compiler's `&Option<T>` into `Option<&T>`

Similar to rust-lang#130962 but for the compiler.

Trying out my new lint rust-lang/rust-clippy#13336 - according to the [video](https://www.youtube.com/watch?v=6c7pZYP_iIE), this could lead to some performance and memory optimizations.
@bors
Copy link
Contributor

bors commented Sep 28, 2024

⌛ Trying commit 340bd2a with merge aabe0bd...

@bors
Copy link
Contributor

bors commented Sep 28, 2024

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

@rust-timer

This comment has been minimized.

@petrochenkov petrochenkov removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 28, 2024
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (aabe0bd): comparison URL.

Overall result: no relevant changes - 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 benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

Results (primary 2.4%)

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.4% [2.4%, 2.4%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.4% [2.4%, 2.4%] 1

Cycles

Results (secondary -2.7%)

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)
- - 0
Improvements ✅
(secondary)
-2.7% [-3.1%, -1.9%] 3
All ❌✅ (primary) - - 0

Binary size

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

Bootstrap: 774.209s -> 771.637s (-0.33%)
Artifact size: 341.42 MiB -> 341.36 MiB (-0.02%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Sep 28, 2024
@petrochenkov petrochenkov added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 29, 2024
@nyurik
Copy link
Contributor Author

nyurik commented Sep 30, 2024

It seems some performance benchmarks are positive, while others are unchanged. While perf was not the primary reason for this PR, it could be a good bonus. I tried running this benchmark (assuming I got it done right), it shows about 11% difference. If I change Option<Vec<usize>> to Option<(usize, usize)>, the difference grows to about 20%.

use criterion::{criterion_group, criterion_main, Criterion};

#[inline(never)]
pub fn do_ref(val: &Option<Vec<usize>>) -> usize {
    match val {
        None => 42,
        Some(val) => val.iter().sum(),
    }
}

#[inline(never)]
pub fn do_as_ref(val: Option<&Vec<usize>>) -> usize {
    match val {
        None => 42,
        Some(val) => val.iter().sum(),
    }
}

fn criterion_benchmark(c: &mut Criterion) {
    let data: Option<Vec<usize>> = Some(vec![0; 2]);
    c.bench_function("ref", |b| b.iter(|| do_ref(&data)));
    c.bench_function("as_ref", |b| b.iter(|| do_as_ref(data.as_ref())));
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

@petrochenkov
Copy link
Contributor

I don't think it always makes sense.

For example, in AST "qualified path" nodes are always stored as Option<P<ast::QSelf>>, so for code working with AST nodes (e.g. AST lowering) it's reasonable to take &Option<P<ast::QSelf>> to avoid many .as_ref()s.

I suggest the following policy: if the function is not public to other crates and all its calls require as_ref after the "&Option<T> -> Option<&T>" conversion, then keep &Option<T>.

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 9, 2024
@nyurik
Copy link
Contributor Author

nyurik commented Oct 9, 2024

I don't think it always makes sense.

For example, in AST "qualified path" nodes are always stored as Option<P<ast::QSelf>>, so for code working with AST nodes (e.g. AST lowering) it's reasonable to take &Option<P<ast::QSelf>> to avoid many .as_ref()s.

I suggest the following policy: if the function is not public to other crates and all its calls require as_ref after the "&Option<T> -> Option<&T>" conversion, then keep &Option<T>.

@rustbot author

Thanks for the feedback. My only concern with this is that we will miss some performance optimizations. The as_ref() are more verbose than & for sure, and I guess a more in-depth study of their effect is warranted, possibly even introducing a new as_ref() operator... @ or ~ ... (github has 1.5 million of them, but that requires waaaay more thinking). But it seems code style at the expense of ergonomics / performance... and yes, style is also part of ergonomics, making it even more complex.

@bors
Copy link
Contributor

bors commented Nov 4, 2024

☔ The latest upstream changes (presumably #132250) made this pull request unmergeable. Please resolve the merge conflicts.

@Dylan-DPC
Copy link
Member

@nyurik any updates on this? thanks

@rust-log-analyzer

This comment has been minimized.

@nyurik
Copy link
Contributor Author

nyurik commented Nov 30, 2024

@Dylan-DPC thx for the heads up. I updated the PR, but I think my comment is still relevant.

@bors
Copy link
Contributor

bors commented Dec 10, 2024

☔ The latest upstream changes (presumably #129514) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented Dec 16, 2024

☔ The latest upstream changes (presumably #134395) made this pull request unmergeable. Please resolve the merge conflicts.

@rust-log-analyzer

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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