Skip to content

Commit 2b8fbe6

Browse files
committed
Auto merge of #82855 - jyn514:no-temporaries, r=GuillaumeGomez
Avoid temporary allocations in `render_assoc_item` `render_assoc_item` came up as very hot in a profile of rustdoc on `bevy`. This avoids some temporary allocations just to calculate the length of the header. This should be a strict improvement, since all string formatting was done twice before. cc #82845
2 parents 142c831 + 1e6d849 commit 2b8fbe6

File tree

2 files changed

+30
-18
lines changed

2 files changed

+30
-18
lines changed

src/librustdoc/html/format.rs

+4
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ impl Buffer {
105105
crate fn is_for_html(&self) -> bool {
106106
self.for_html
107107
}
108+
109+
crate fn reserve(&mut self, additional: usize) {
110+
self.buffer.reserve(additional)
111+
}
108112
}
109113

110114
/// Wrapper struct for properly emitting a function or method declaration.

src/librustdoc/html/render/mod.rs

+26-18
Original file line numberDiff line numberDiff line change
@@ -1009,36 +1009,44 @@ fn render_assoc_item(
10091009
href(did, cx.cache()).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor)
10101010
}
10111011
};
1012-
let mut header_len = format!(
1013-
"{}{}{}{}{}{:#}fn {}{:#}",
1014-
meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache()),
1015-
header.constness.print_with_space(),
1016-
header.asyncness.print_with_space(),
1017-
header.unsafety.print_with_space(),
1018-
print_default_space(meth.is_default()),
1019-
print_abi_with_space(header.abi),
1020-
name,
1021-
g.print(cx.cache())
1022-
)
1023-
.len();
1012+
let tcx = cx.tcx();
1013+
let vis = meth.visibility.print_with_space(tcx, meth.def_id, cx.cache()).to_string();
1014+
let constness = header.constness.print_with_space();
1015+
let asyncness = header.asyncness.print_with_space();
1016+
let unsafety = header.unsafety.print_with_space();
1017+
let defaultness = print_default_space(meth.is_default());
1018+
let abi = print_abi_with_space(header.abi).to_string();
1019+
// NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`.
1020+
let generics_len = format!("{:#}", g.print(cx.cache())).len();
1021+
let mut header_len = "fn ".len()
1022+
+ vis.len()
1023+
+ constness.len()
1024+
+ asyncness.len()
1025+
+ unsafety.len()
1026+
+ defaultness.len()
1027+
+ abi.len()
1028+
+ name.as_str().len()
1029+
+ generics_len;
1030+
10241031
let (indent, end_newline) = if parent == ItemType::Trait {
10251032
header_len += 4;
10261033
(4, false)
10271034
} else {
10281035
(0, true)
10291036
};
10301037
render_attributes(w, meth, false);
1038+
w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len());
10311039
write!(
10321040
w,
10331041
"{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\
10341042
{generics}{decl}{spotlight}{where_clause}",
10351043
if parent == ItemType::Trait { " " } else { "" },
1036-
meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache()),
1037-
header.constness.print_with_space(),
1038-
header.asyncness.print_with_space(),
1039-
header.unsafety.print_with_space(),
1040-
print_default_space(meth.is_default()),
1041-
print_abi_with_space(header.abi),
1044+
vis,
1045+
constness,
1046+
asyncness,
1047+
unsafety,
1048+
defaultness,
1049+
abi,
10421050
href = href,
10431051
name = name,
10441052
generics = g.print(cx.cache()),

0 commit comments

Comments
 (0)