Skip to content

Commit

Permalink
Improve performance of String::from_str_in
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel authored and fitzgen committed Feb 14, 2024
1 parent 1d31c76 commit 7b3fd17
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 2 deletions.
23 changes: 23 additions & 0 deletions benches/benches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ fn format_realloc(bump: &bumpalo::Bump, n: usize) {
criterion::black_box(s);
}

#[cfg(feature = "collections")]
fn string_from_str_in(bump: &bumpalo::Bump, str: &str) {
let str = criterion::black_box(str);
let s = bumpalo::collections::string::String::from_str_in(str, bump);
criterion::black_box(s);
}

#[cfg(feature = "collections")]
fn string_push_str(bump: &bumpalo::Bump, str: &str) {
let str = criterion::black_box(str);
Expand Down Expand Up @@ -210,6 +217,21 @@ fn bench_format_realloc(c: &mut Criterion) {
}
}

fn bench_string_from_str_in(c: &mut Criterion) {
let len: usize = 16;

let mut group = c.benchmark_group("alloc");
group.throughput(Throughput::Elements(len as u64));
group.bench_function("from_str_in", |b| {
let mut bump = bumpalo::Bump::with_capacity(len);
let str = "x".repeat(len);
b.iter(|| {
bump.reset();
string_from_str_in(&bump, &*str);
});
});
}

fn bench_string_push_str(c: &mut Criterion) {
let len: usize = 16 * 1024; // 16 KiB

Expand All @@ -236,6 +258,7 @@ criterion_group!(
bench_try_alloc_try_with,
bench_try_alloc_try_with_err,
bench_format_realloc,
bench_string_from_str_in,
bench_string_push_str
);
criterion_main!(benches);
15 changes: 13 additions & 2 deletions src/collections/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,8 +680,19 @@ impl<'bump> String<'bump> {
/// assert_eq!(s, "hello");
/// ```
pub fn from_str_in(s: &str, bump: &'bump Bump) -> String<'bump> {
let mut t = String::with_capacity_in(s.len(), bump);
t.push_str(s);
let len = s.len();
let mut t = String::with_capacity_in(len, bump);
// SAFETY:
// * `src` is valid for reads of `s.len()` bytes by virtue of being an allocated `&str`.
// * `dst` is valid for writes of `s.len()` bytes as `String::with_capacity_in(s.len(), bump)`
// above guarantees that.
// * Alignment is not relevant as `u8` has no alignment requirements.
// * Source and destination ranges cannot overlap as we just reserved the destination
// range from the bump.
unsafe { ptr::copy_nonoverlapping(s.as_ptr(), t.vec.as_mut_ptr(), len) };
// SAFETY: We reserved sufficent capacity for the string above.
// The elements at `0..len` were initialized by `copy_nonoverlapping` above.
unsafe { t.vec.set_len(len) };
t
}

Expand Down

0 comments on commit 7b3fd17

Please sign in to comment.