Skip to content

Commit 36de490

Browse files
committed
[DO NOT MERGE] Experiment with micro-optimizing push_str calls
1 parent b01cc1c commit 36de490

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

library/alloc/src/string.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,22 @@ impl String {
11121112
self.vec.extend_from_slice(string.as_bytes())
11131113
}
11141114

1115+
#[unstable(feature = "string_push_str_slice", issue = "none")]
1116+
#[inline]
1117+
pub fn push_str_slice(&mut self, slice: &[&str]) {
1118+
let additional = slice.iter().map(|x| x.len()).sum();
1119+
self.reserve(additional);
1120+
let (ptr, len, cap) = core::mem::take(self).into_raw_parts();
1121+
unsafe {
1122+
let mut dst = ptr.add(len);
1123+
for new in slice {
1124+
core::ptr::copy_nonoverlapping(new.as_ptr(), dst, new.len());
1125+
dst = dst.add(new.len());
1126+
}
1127+
*self = String::from_raw_parts(ptr, len + additional, cap);
1128+
}
1129+
}
1130+
11151131
/// Copies elements from `src` range to the end of the string.
11161132
///
11171133
/// # Panics

src/librustdoc/html/render/print_item.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,8 +2257,7 @@ pub(crate) fn compare_names(left: &str, right: &str) -> Ordering {
22572257

22582258
pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
22592259
let mut s = join_path_syms(&cx.current);
2260-
s.push_str("::");
2261-
s.push_str(item.name.unwrap().as_str());
2260+
crate::push_str_slice(&mut s, &["::", item.name.unwrap().as_str()]);
22622261
s
22632262
}
22642263

src/librustdoc/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#![feature(rustc_private)]
1919
#![feature(test)]
2020
#![feature(trim_prefix_suffix)]
21+
#![feature(vec_into_raw_parts)]
2122
#![warn(rustc::internal)]
2223
// tidy-alphabetical-end
2324

@@ -983,3 +984,19 @@ fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) {
983984
tcxt.dcx().err(format!("cannot emit feature usage metrics: {error}"));
984985
}
985986
}
987+
988+
#[inline]
989+
fn push_str_slice(s: &mut String, slice: &[&str]) {
990+
use std::ptr::copy_nonoverlapping;
991+
let additional = slice.iter().map(|x| x.len()).sum();
992+
s.reserve(additional);
993+
let (ptr, len, cap) = std::mem::take(s).into_raw_parts();
994+
unsafe {
995+
let mut dst = ptr.add(len);
996+
for new in slice {
997+
copy_nonoverlapping(new.as_ptr(), dst, new.len());
998+
dst = dst.add(new.len());
999+
}
1000+
*s = String::from_raw_parts(ptr, len + additional, cap);
1001+
}
1002+
}

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,17 +223,18 @@ impl UrlFragment {
223223
DefKind::Field => {
224224
let parent_id = tcx.parent(def_id);
225225
if tcx.def_kind(parent_id) == DefKind::Variant {
226-
s.push_str("variant.");
227-
s.push_str(tcx.item_name(parent_id).as_str());
226+
crate::push_str_slice(
227+
s,
228+
&["variant.", tcx.item_name(parent_id).as_str()],
229+
);
228230
".field."
229231
} else {
230232
"structfield."
231233
}
232234
}
233235
kind => bug!("unexpected associated item kind: {kind:?}"),
234236
};
235-
s.push_str(kind);
236-
s.push_str(tcx.item_name(def_id).as_str());
237+
crate::push_str_slice(s, &[kind, tcx.item_name(def_id).as_str()]);
237238
}
238239
UrlFragment::UserWritten(raw) => s.push_str(raw),
239240
}

0 commit comments

Comments
 (0)