diff --git a/benches/bench.rs b/benches/bench.rs index b00a1c0..238caed 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -39,7 +39,7 @@ criterion_main!(bench_get_or_intern, bench_resolve, bench_get, bench_iter); fn bench_get_or_intern_static(c: &mut Criterion) { let mut g = c.benchmark_group("get_or_intern_static"); - fn bench_for_backend(g: &mut BenchmarkGroup) { + fn bench_for_backend<'i, BB: BackendBenchmark<'i>>(g: &mut BenchmarkGroup) { #[rustfmt::skip] let static_strings = &[ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", @@ -87,7 +87,7 @@ fn bench_get_or_intern_static(c: &mut Criterion) { fn bench_get_or_intern_fill_with_capacity(c: &mut Criterion) { let mut g = c.benchmark_group("get_or_intern/fill-empty/with_capacity"); g.throughput(Throughput::Elements(BENCH_LEN_STRINGS as u64)); - fn bench_for_backend(g: &mut BenchmarkGroup) { + fn bench_for_backend<'i, BB: BackendBenchmark<'i>>(g: &mut BenchmarkGroup) { g.bench_with_input( BB::NAME, &(BENCH_LEN_STRINGS, BENCH_STRING_LEN), @@ -113,7 +113,7 @@ fn bench_get_or_intern_fill_with_capacity(c: &mut Criterion) { fn bench_get_or_intern_fill(c: &mut Criterion) { let mut g = c.benchmark_group("get_or_intern/fill-empty/new"); g.throughput(Throughput::Elements(BENCH_LEN_STRINGS as u64)); - fn bench_for_backend(g: &mut BenchmarkGroup) { + fn bench_for_backend<'i, BB: BackendBenchmark<'i>>(g: &mut BenchmarkGroup) { g.bench_with_input( BB::NAME, &(BENCH_LEN_STRINGS, BENCH_STRING_LEN), @@ -139,7 +139,7 @@ fn bench_get_or_intern_fill(c: &mut Criterion) { fn bench_get_or_intern_already_filled(c: &mut Criterion) { let mut g = c.benchmark_group("get_or_intern/already-filled"); g.throughput(Throughput::Elements(BENCH_LEN_STRINGS as u64)); - fn bench_for_backend(g: &mut BenchmarkGroup) { + fn bench_for_backend<'i, BB: BackendBenchmark<'i>>(g: &mut BenchmarkGroup) { g.bench_with_input( BB::NAME, &(BENCH_LEN_STRINGS, BENCH_STRING_LEN), @@ -165,7 +165,7 @@ fn bench_get_or_intern_already_filled(c: &mut Criterion) { fn bench_resolve_already_filled(c: &mut Criterion) { let mut g = c.benchmark_group("resolve/already-filled"); g.throughput(Throughput::Elements(BENCH_LEN_STRINGS as u64)); - fn bench_for_backend(g: &mut BenchmarkGroup) { + fn bench_for_backend<'i, BB: BackendBenchmark<'i>>(g: &mut BenchmarkGroup) { g.bench_with_input( BB::NAME, &(BENCH_LEN_STRINGS, BENCH_STRING_LEN), @@ -191,7 +191,7 @@ fn bench_resolve_already_filled(c: &mut Criterion) { fn bench_resolve_unchecked_already_filled(c: &mut Criterion) { let mut g = c.benchmark_group("resolve_unchecked/already-filled"); g.throughput(Throughput::Elements(BENCH_LEN_STRINGS as u64)); - fn bench_for_backend(g: &mut BenchmarkGroup) { + fn bench_for_backend<'i, BB: BackendBenchmark<'i>>(g: &mut BenchmarkGroup) { g.bench_with_input( BB::NAME, &(BENCH_LEN_STRINGS, BENCH_STRING_LEN), @@ -220,7 +220,7 @@ fn bench_resolve_unchecked_already_filled(c: &mut Criterion) { fn bench_get_already_filled(c: &mut Criterion) { let mut g = c.benchmark_group("get/already-filled"); g.throughput(Throughput::Elements(BENCH_LEN_STRINGS as u64)); - fn bench_for_backend(g: &mut BenchmarkGroup) { + fn bench_for_backend<'i, BB: BackendBenchmark<'i>>(g: &mut BenchmarkGroup) { g.bench_with_input( BB::NAME, &(BENCH_LEN_STRINGS, BENCH_STRING_LEN), @@ -246,11 +246,11 @@ fn bench_get_already_filled(c: &mut Criterion) { fn bench_iter_already_filled(c: &mut Criterion) { let mut g = c.benchmark_group("iter/already-filled"); g.throughput(Throughput::Elements(BENCH_LEN_STRINGS as u64)); - fn bench_for_backend(g: &mut BenchmarkGroup) + fn bench_for_backend<'i, BB: BackendBenchmark<'i>>(g: &mut BenchmarkGroup) where - for<'a> &'a ::Backend: IntoIterator< + for<'a> &'a >::Backend: IntoIterator< Item = ( - <::Backend as Backend>::Symbol, + <>::Backend as Backend<'i>>::Symbol, &'a str, ), >, diff --git a/benches/setup.rs b/benches/setup.rs index cb8adcc..5428692 100644 --- a/benches/setup.rs +++ b/benches/setup.rs @@ -1,7 +1,6 @@ use string_interner::{ backend::{Backend, BucketBackend, BufferBackend, StringBackend}, - DefaultSymbol, - StringInterner, + DefaultSymbol, StringInterner, }; /// Alphabet containing all characters that may be put into a benchmark string. @@ -79,53 +78,64 @@ pub const BENCH_LEN_STRINGS: usize = 100_000; pub const BENCH_STRING_LEN: usize = 5; type FxBuildHasher = fxhash::FxBuildHasher; -type StringInternerWith = StringInterner; +type StringInternerWith<'i, B> = StringInterner<'i, B, FxBuildHasher>; -pub trait BackendBenchmark { +pub trait BackendBenchmark<'i> { const NAME: &'static str; - type Backend: Backend; + type Backend: Backend<'i>; - fn setup() -> StringInternerWith { + fn setup() -> StringInternerWith<'i, Self::Backend> { >::new() } - fn setup_with_capacity(cap: usize) -> StringInternerWith { + fn setup_with_capacity(cap: usize) -> StringInternerWith<'i, Self::Backend> { >::with_capacity(cap) } - fn setup_filled(words: &[String]) -> StringInternerWith { - words.iter().collect::>() + fn setup_filled(words: I) -> StringInternerWith<'i, Self::Backend> + where + I: IntoIterator, + S: AsRef, + { + words + .into_iter() + .map(|it| it.as_ref().to_string()) + .collect::>() } - fn setup_filled_with_ids( - words: &[String], + fn setup_filled_with_ids( + words: I, ) -> ( - StringInternerWith, - Vec<::Symbol>, - ) { - let mut interner = >::new(); + StringInternerWith<'i, Self::Backend>, + Vec<>::Symbol>, + ) + where + I: IntoIterator, + S: AsRef, + { + let mut interner = >::new(); let word_ids = words - .iter() - .map(|word| interner.get_or_intern(word)) + .into_iter() + .map(|word| interner.get_or_intern(word.as_ref())) .collect::>(); (interner, word_ids) } } pub struct BenchBucket; -impl BackendBenchmark for BenchBucket { +impl<'i> BackendBenchmark<'i> for BenchBucket { const NAME: &'static str = "BucketBackend"; - type Backend = BucketBackend; + type Backend = BucketBackend<'i, DefaultSymbol>; } pub struct BenchString; -impl BackendBenchmark for BenchString { +impl<'i> BackendBenchmark<'i> for BenchString { const NAME: &'static str = "StringBackend"; - type Backend = StringBackend; + type Backend = StringBackend<'i, DefaultSymbol>; } pub struct BenchBuffer; -impl BackendBenchmark for BenchBuffer { +impl<'i> BackendBenchmark<'i> for BenchBuffer { const NAME: &'static str = "BufferBackend"; - type Backend = BufferBackend; + type Backend = BufferBackend<'i, DefaultSymbol>; } diff --git a/src/backend/buffer.rs b/src/backend/buffer.rs index df59121..6cbd5bf 100644 --- a/src/backend/buffer.rs +++ b/src/backend/buffer.rs @@ -7,8 +7,7 @@ use core::{mem, str}; /// An interner backend that concatenates all interned string contents into one large /// buffer [`Vec`]. Unlike [`StringBackend`][crate::backend::StringBackend], string -/// lengths are stored in the same buffer as strings preceeding the respective string -/// data. +/// lengths are stored in the same buffer as strings preceeding the respective string data. /// /// ## Trade-offs /// - **Advantages:**