-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
perf: Delay formatting of lint messages until they are know to be used #67755
Conversation
Found `check` builts in one of my crates spent 5% of the time just formatting types for the sake of the `BoxPointers` lint, only for the strings to get thrown away immediately since it is an `allow` lint. This does the bare minimum to instead pass a `fmt::Display` instance to the lint so that `msg` may only be created if it is needed. Unsure if this is the desired way to solve this problem so I didn't go through the lint system throughly to see if there were more places that should take/pass `format_args!` instances instead of using `format!`.
r? @eddyb (rust_highfive has picked a reviewer for you, use r? to override) |
@bors try @rust-timer queue |
Awaiting bors try build completion |
perf: Delay formatting of lint messages until they are know to be used Found that (touch+) `check` builds in one of my crates spent 5% of the time just formatting types for the sake of the `BoxPointers` lint, only for the strings to get thrown away immediately since it is an `allow` lint. This does the bare minimum to instead pass a `fmt::Display` instance to the lint so that `msg` may only be created if it is needed. Unsure if this is the desired way to solve this problem so I didn't go through the lint system throughly to see if there were more places that should take/pass `format_args!` instances instead of using `format!`.
level: Level, | ||
src: LintSource, | ||
span: Option<MultiSpan>, | ||
msg: &dyn std::fmt::Display, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... this does nothing though to prevent similar mistakes in the future.
Perhaps we should:
-
Set the initial message to
""
(so there should be no allocation). -
Invert control: Instead of returning a
DiagnosticBuilder<'_>
, we take in a functionimpl Fn(&mut DiagnosticBuilder<'_>)
which allows the caller to make modifications, but ultimately this is never called onLevel::Allow
, thereby avoiding allocations that follow in e.g.rust/src/librustc_lint/builtin.rs
Lines 190 to 200 in 055ce62
let binding = match binding_annot { hir::BindingAnnotation::Unannotated => None, hir::BindingAnnotation::Mutable => Some("mut"), hir::BindingAnnotation::Ref => Some("ref"), hir::BindingAnnotation::RefMut => Some("ref mut"), }; let ident = if let Some(binding) = binding { format!("{} {}", binding, ident) } else { ident.to_string() };
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the idea of changing the api surface to always defer evaluation of the message would be a relatively painless big win.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed #67927.
☀️ Try build successful - checks-azure |
Queued 228ed11 with parent 71bb0ff, future comparison URL. |
Finished benchmarking try commit 228ed11, comparison URL. |
cc @rust-lang/wg-diagnostics r? @oli-obk |
@Marwes can you rebase this? Thanks |
It looks like there is in progress work to further improve this ( #67927 ) so maybe this should just be closed? |
Closing it then. Thanks :) |
I feel like merging this PR is a reasonable stop gap measure, if you wish to put in the work to clean it up @Marwes. |
Looks like things have changed quite a bit (files deleted/moved) so I will leave this alone. Got other performance PRs that needs investigation anyways. |
Found that (touch+)
check
builds in one of my crates spent 5% of the time justformatting types for the sake of the
BoxPointers
lint, only for thestrings to get thrown away immediately since it is an
allow
lint.This does the bare minimum to instead pass a
fmt::Display
instance tothe lint so that
msg
may only be created if it is needed.Unsure if this is the desired way to solve this problem so I didn't go
through the lint system throughly to see if there were more places that
should take/pass
format_args!
instances instead of usingformat!
.