Optimize handling of solver errors - #160160
Conversation
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Check for the empty case in `collect_remaining_errors()`
|
|
||
| fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> { | ||
| #[allow(clippy::iter_skip_zero)] | ||
| if self.obligations.pending.is_empty() && self.obligations.overflowed.is_empty() { | ||
| // In 99.983% this is true, so this helps perf. | ||
| return Vec::new(); | ||
| } | ||
|
|
||
| self.obligations |
There was a problem hiding this comment.
One other thing I'd try later too is that sometimes it helps is to put #[inline] on the function and wrap the rest of the code after the fast path in outline(move || { ... })).
There was a problem hiding this comment.
True, I also wanted to check if making this ThinVec will help since it will return in a register. It may cancel with outlining though.
|
@bors cancel |
|
❗ There is currently no auto build in progress on this PR. Hint: There is a pending try build on this PR. Maybe you meant to cancel it? You can do that using |
|
@bors try cancel |
|
Try build cancelled. Cancelled workflows: |
1223716 to
fbe4c63
Compare
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Check for the empty case in `collect_remaining_errors()`
|
I think it's worth checking this in std's TrustedLen specializations. The code is querying the size-hint anyway, it might as well bail early rather than invoking the |
|
It might be interesting, but std's specialization applies to much more diverse range of behaviors. There we can't know if "empty most of the times" is the common case. |
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (f5bcd01): comparison URL. Overall result: ✅ improvements - no action neededBenchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up. @rustbot label: -S-waiting-on-perf -perf-regression Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -3.6%, secondary 0.7%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 0.4%, secondary 0.5%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis perf run didn't have relevant results for this metric. Bootstrap: 489.658s -> 489.161s (-0.10%) |
|
Okay, so not only this does not regress #160073 this also has a non-negligible improvement. Seems worth to merge, but I'll try to see if I can use |
|
Yea, the |
|
|
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Check for the empty case in `collect_remaining_errors()`
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (79906d6): comparison URL. Overall result: ❌✅ regressions and improvements - please read:Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf. Next, please: If you can, justify the regressions found in this try perf run in writing along with @bors rollup=never rustc-perf Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -0.1%, secondary -0.1%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 0.1%, secondary 0.4%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (secondary 0.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 489.76s -> 487.975s (-0.36%) |
|
Improvements greatly outweigh regressions, including in non-next-solver benchmarks. Seems like this was a good idea. |
|
Some changes occurred in cc @BoxyUwU Some changes occurred to the core trait solver cc @rust-lang/initiative-trait-system-refactor
cc @rust-lang/clippy Some changes occurred to the CTFE machinery Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt Some changes occurred in engine.rs, potentially modifying the public API of cc @lcnr HIR ty lowering was modified cc @fmease Some changes occurred to constck cc @fee1-dead Some changes occurred in compiler/rustc_passes/src/check_attr.rs cc @jdonszelmann, @JonathanBrouwer Some changes occurred to the CTFE / Miri interpreter cc @rust-lang/miri |
|
r? @TaKO8Ki rustbot has assigned @TaKO8Ki. Use Why was this reviewer chosen?The reviewer was selected based on:
|
|
To the reviewer: The commits are fully separate. I can create separate PRs, but the first commit is very small so I don't think it's needed. |
collect_remaining_errors()As it's very common.
This has multiple advantages: - Performance. The new type is 1/3 the size of `Vec` (being equivalent in layout to `Option<ThinVec>`) and can be kept in a register. - Type safety. We mark the type `#[must_use]`, and thinks requiring errors take `ThinVec`, which requires unwrapping the type and verifying there is indeed an error. We still provide conversions to slices, `ThinVec`, and iteration, because some code needs this and I saw no benefit in changing it, but we deliberately do not provide `Deref<Target = [E]>` or things like that.
6f6965c to
838f636
Compare
View all comments
Check for the empty case in
collect_remaining_errors().Instead of representing trait errors as
Vec<Error>, use a special typeThis has multiple advantages:
Vec(being equivalent in layout toOption<ThinVec>) and can be kept in a register.#[must_use], and thinks requiring errors takeThinVec, which requires unwrapping the type and verifying there is indeed an error. We still provide conversions to slices,ThinVec, and iteration, because some code needs this and I saw no benefit in changing it, but we deliberately do not provideDeref<Target = [E]>or things like that.