diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs
index 91e098979acf..cc4a7f37fe9a 100644
--- a/src/librustdoc/html/length_limit.rs
+++ b/src/librustdoc/html/length_limit.rs
@@ -29,8 +29,18 @@ pub(super) struct HtmlWithLimit {
impl HtmlWithLimit {
/// Create a new buffer, with a limit of `length_limit`.
pub(super) fn new(length_limit: usize) -> Self {
+ let buf = if length_limit > 1000 {
+ // If the length limit is really large, don't preallocate tons of memory.
+ String::new()
+ } else {
+ // The length limit is actually a good heuristic for initial allocation size.
+ // Measurements showed that using it as the initial capacity ended up using less memory
+ // than `String::new`.
+ // See https://github.com/rust-lang/rust/pull/88173#discussion_r692531631 for more.
+ String::with_capacity(length_limit)
+ };
Self {
- buf: String::new(),
+ buf,
len: 0,
limit: length_limit,
unclosed_tags: Vec::new(),
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 5a569c690e54..b2ca13499818 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1096,7 +1096,6 @@ fn markdown_summary_with_limit(
let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
let mut p = LinkReplacer::new(p, link_names);
- // FIXME: capacity
let mut buf = HtmlWithLimit::new(length_limit);
let mut stopped_early = false;
p.try_for_each(|event| {