Auto merge of #109399 - petrochenkov:rendersort, r=GuillaumeGomez
rustdoc: Optimize impl sorting during rendering This should fix the perf regression on [bitmaps-3.1.0](https://github.com/rust-lang/rustc-perf/tree/master/collector/compile-benchmarks/bitmaps-3.1.0) from https://github.com/rust-lang/rust/pull/107765. The bitmaps crate has a lot of impls: ```rust impl Bits for BitsImpl<1> { ... } impl Bits for BitsImpl<2> { ... } // ... impl Bits for BitsImpl<1023> { ... } impl Bits for BitsImpl<1024> { ... } ``` and the logic in `fn print_item` sorts them in natural order. Before https://github.com/rust-lang/rust/pull/107765 the impls came in source order, which happened to be already sorted in the necessary way. So the comparison function was called fewer times. After https://github.com/rust-lang/rust/pull/107765 the impls came in "stable" order (based on def path hash). So the comparison function was called more times to sort them. The comparison function was terribly inefficient, so it caused a large perf regression. This PR attempts to make it more efficient by using cached keys during sorting.
This commit is contained in:
commit
d012d2f96e
@ -880,8 +880,8 @@ fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::
|
||||
let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
|
||||
local.iter().partition(|i| i.inner_impl().kind.is_auto());
|
||||
|
||||
synthetic.sort_by(|a, b| compare_impl(a, b, cx));
|
||||
concrete.sort_by(|a, b| compare_impl(a, b, cx));
|
||||
synthetic.sort_by_cached_key(|i| ImplString::new(i, cx));
|
||||
concrete.sort_by_cached_key(|i| ImplString::new(i, cx));
|
||||
|
||||
if !foreign.is_empty() {
|
||||
write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "");
|
||||
@ -1597,12 +1597,25 @@ fn wrap_item<F>(w: &mut Buffer, f: F)
|
||||
w.write_str("</code></pre>");
|
||||
}
|
||||
|
||||
fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cx: &Context<'_>) -> Ordering {
|
||||
let lhss = format!("{}", lhs.inner_impl().print(false, cx));
|
||||
let rhss = format!("{}", rhs.inner_impl().print(false, cx));
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct ImplString(String);
|
||||
|
||||
// lhs and rhs are formatted as HTML, which may be unnecessary
|
||||
compare_names(&lhss, &rhss)
|
||||
impl ImplString {
|
||||
fn new(i: &Impl, cx: &Context<'_>) -> ImplString {
|
||||
ImplString(format!("{}", i.inner_impl().print(false, cx)))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for ImplString {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(Ord::cmp(self, other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for ImplString {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
compare_names(&self.0, &other.0)
|
||||
}
|
||||
}
|
||||
|
||||
fn render_implementor(
|
||||
|
Loading…
Reference in New Issue
Block a user