diff --git a/benches/bench.rs b/benches/bench.rs index a0da60b..f87796e 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -263,6 +263,124 @@ fn vec_u_vn_s_prealloc(bencher: &mut Bencher) { ); } +#[bench] +fn empty_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized(bencher, vec![(); 1024]); +} +#[bench] +fn u64_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized(bencher, vec![0u64; 1024]); +} +#[bench] +fn u32x2_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized(bencher, vec![(0u32, 0u32); 1024]); +} +#[bench] +fn u8_u64_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized(bencher, vec![(0u8, 0u64); 512]); +} +#[bench] +fn str10_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized(bencher, vec!["grawwwwrr!"; 1024]); +} +#[bench] +fn str100_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized(bencher, vec!["grawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrr!!!!!!!!!grawwwwrr!"; 1024]); +} +#[bench] +fn string10_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized(bencher, vec![format!("grawwwwrr!"); 1024]); +} +#[bench] +fn string20_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized(bencher, vec![format!("grawwwwrr!!!!!!!!!!!"); 512]); +} +#[bench] +fn vec_u_s_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized( + bencher, + vec![vec![(0u64, "grawwwwrr!".to_string()); 32]; 32], + ); +} +#[bench] +fn vec_u_vn_s_copy_flat(bencher: &mut Bencher) { + _bench_copy_flat_containerized( + bencher, + vec![vec![(0u64, vec![(); 1 << 40], "grawwwwrr!".to_string()); 32]; 32], + ); +} + +#[bench] +fn empty_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::, _>(bencher, vec![(); 1024]); +} +#[bench] +fn u64_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::, _>(bencher, vec![0u64; 1024]); +} +#[bench] +fn u32x2_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::, _>(bencher, vec![(0u32, 0u32); 1024]); +} +#[bench] +fn u8_u64_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::, _>(bencher, vec![(0u8, 0u64); 512]); +} +#[bench] +fn str10_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::, _>(bencher, vec!["grawwwwrr!"; 1024]); +} +#[bench] +fn str100_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::, _>(bencher, vec!["grawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrrgrawwwwrr!!!!!!!!!grawwwwrr!"; 1024]); +} +#[bench] +fn string10_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::, _>(bencher, vec![format!("grawwwwrr!"); 1024]); +} +#[bench] +fn string20_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::, _>( + bencher, + vec![format!("grawwwwrr!!!!!!!!!!!"); 512], + ); +} +#[bench] +fn vec_u_s_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::, StringRegion>>>, _>( + bencher, + vec![vec![(0u64, "grawwwwrr!".to_string()); 32]; 32], + ); +} +#[bench] +fn vec_u_vn_s_copy_flat_region(bencher: &mut Bencher) { + _bench_copy_flat::< + SliceRegion, OwnedRegion<_>, StringRegion>>>, + _, + >( + bencher, + vec![vec![(0u64, vec![(); 1 << 40], "grawwwwrr!".to_string()); 32]; 32], + ); +} +#[bench] +fn vec_u_vn_s_copy_flat_region_column(bencher: &mut Bencher) { + _bench_copy_flat::< + SliceRegion< + ColumnsRegion< + TupleABCRegion< + MirrorRegion<_>, + CollapseSequence>, + CollapseSequence, + >, + >, + >, + _, + >( + bencher, + vec![vec![(0u64, vec![(); 1 << 40], "grawwwwrr!".to_string()); 32]; 32], + ); +} + fn _bench_copy(bencher: &mut Bencher, record: T) where for<'a> ::Region: Push<&'a T>, @@ -281,6 +399,7 @@ where siz += this_siz; cap += this_cap }); + bencher.bytes = siz as u64; println!("{siz} {cap}"); } @@ -302,6 +421,7 @@ where siz += this_siz; cap += this_cap }); + bencher.bytes = siz as u64; println!("{siz} {cap}"); } @@ -321,25 +441,71 @@ fn _bench_realloc(bencher: &mut Bencher, record: T) where for<'a> ::Region: Push<&'a T>, { + let mut arena = FlatStack::default_impl::(); bencher.iter(|| { // prepare encoded data for bencher.bytes - let mut arena = FlatStack::default_impl::(); + arena = FlatStack::default_impl::(); for _ in 0..1024 { arena.copy(&record); } }); + let (mut siz, mut cap) = (0, 0); + arena.heap_size(|this_siz, this_cap| { + siz += this_siz; + cap += this_cap + }); + bencher.bytes = siz as u64; } fn _bench_prealloc(bencher: &mut Bencher, record: T) where for<'a> ::Region: ReserveItems<&'a T> + Push<&'a T>, { + let mut arena = FlatStack::default_impl::(); bencher.iter(|| { + arena = FlatStack::default_impl::(); // prepare encoded data for bencher.bytes - let mut arena = FlatStack::default_impl::(); arena.reserve_items(std::iter::repeat(&record).take(1024)); for _ in 0..1024 { arena.copy(&record); } }); + let (mut siz, mut cap) = (0, 0); + arena.heap_size(|this_siz, this_cap| { + siz += this_siz; + cap += this_cap + }); + bencher.bytes = siz as u64; +} + +fn _bench_copy_flat_containerized(bencher: &mut Bencher, record: T) +where + T: Containerized, + for<'a> ::Region: + Push<&'a T> + Push<<::Region as Region>::ReadItem<'a>> + Clone, +{ + _bench_copy_flat::(bencher, record) +} + +fn _bench_copy_flat(bencher: &mut Bencher, record: T) +where + for<'a> R: Region + Push<&'a T> + Push<::ReadItem<'a>> + Clone, +{ + // prepare encoded data for bencher.bytes + let mut arena = FlatStack::::default(); + for _ in 0..1024 { + arena.copy(&record); + } + let mut target = FlatStack::::default(); + + bencher.iter(|| { + target.clone_from(&arena); + }); + let (mut siz, mut cap) = (0, 0); + arena.heap_size(|this_siz, this_cap| { + siz += this_siz; + cap += this_cap + }); + bencher.bytes = siz as u64; + println!("{siz} {cap}"); } diff --git a/src/impls/codec.rs b/src/impls/codec.rs index 70e1c38..5e52afb 100644 --- a/src/impls/codec.rs +++ b/src/impls/codec.rs @@ -62,12 +62,25 @@ fn consolidate_slice(slice: &mut [(T, usize)]) -> usize { } /// A region that encodes its data in a codec `C`. -#[derive(Default, Debug, Clone)] -pub struct CodecRegion> { +#[derive(Default, Debug)] +pub struct CodecRegion> { inner: R, codec: C, } +impl Clone for CodecRegion { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + codec: self.codec.clone(), + } + } + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner); + self.codec.clone_from(&source.codec); + } +} + impl Region for CodecRegion where for<'a> R: Region = &'a [u8]> + 'a, @@ -104,6 +117,7 @@ where } fn clear(&mut self) { + self.inner.clear(); self.codec = Default::default(); } diff --git a/src/impls/columns.rs b/src/impls/columns.rs index e142590..e7b97a4 100644 --- a/src/impls/columns.rs +++ b/src/impls/columns.rs @@ -48,7 +48,7 @@ use crate::{OwnedRegion, Push, Region}; /// assert!(row.iter().copied().eq(r.index(index).iter())); /// } /// ``` -#[derive(Debug, Clone)] +#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde", @@ -67,6 +67,23 @@ where inner: Vec, } +impl Clone for ColumnsRegion +where + R: Region + Clone, +{ + fn clone(&self) -> Self { + Self { + indices: self.indices.clone(), + inner: self.inner.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.indices.clone_from(&source.indices); + self.inner.clone_from(&source.inner); + } +} + impl Region for ColumnsRegion where R: Region, diff --git a/src/impls/deduplicate.rs b/src/impls/deduplicate.rs index 73db39b..a015809 100644 --- a/src/impls/deduplicate.rs +++ b/src/impls/deduplicate.rs @@ -18,7 +18,7 @@ use crate::{Push, Region, ReserveItems}; /// /// assert_eq!(r.push("abc"), r.push("abc")); /// ``` -#[derive(Debug, Clone)] +#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct CollapseSequence { /// Inner region. @@ -27,6 +27,20 @@ pub struct CollapseSequence { last_index: Option, } +impl Clone for CollapseSequence { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + last_index: self.last_index, + } + } + + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner); + self.last_index = source.last_index; + } +} + impl Default for CollapseSequence { fn default() -> Self { Self { @@ -114,7 +128,7 @@ where /// let index: usize = r.push(&b"abc"); /// assert_eq!(b"abc", r.index(index)); /// ``` -#[derive(Debug, Clone)] +#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ConsecutiveOffsetPairs where @@ -129,8 +143,30 @@ where last_index: usize, } -impl, O: OffsetContainer> Default - for ConsecutiveOffsetPairs +impl Clone for ConsecutiveOffsetPairs +where + R: Region + Clone, + O: OffsetContainer + Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + offsets: self.offsets.clone(), + last_index: self.last_index, + } + } + + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner); + self.offsets.clone_from(&source.offsets); + self.last_index = source.last_index; + } +} + +impl Default for ConsecutiveOffsetPairs +where + R: Region, + O: OffsetContainer, { #[inline] fn default() -> Self { diff --git a/src/impls/huffman_container.rs b/src/impls/huffman_container.rs index 52c8b4e..75c2086 100644 --- a/src/impls/huffman_container.rs +++ b/src/impls/huffman_container.rs @@ -33,6 +33,20 @@ where } } +impl Clone for HuffmanContainer { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + stats: self.stats.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner); + self.stats.clone_from(&source.stats); + } +} + impl Region for HuffmanContainer where B: Ord + Clone + Sized + 'static, @@ -462,6 +476,21 @@ mod huffman { /// Byte-by-byte decoder. decode: [Decode; 256], } + + impl Clone for Huffman { + fn clone(&self) -> Self { + Self { + encode: self.encode.clone(), + decode: self.decode.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.encode.clone_from(&source.encode); + self.decode.clone_from(&source.decode); + } + } + impl Huffman { /// Encodes the provided symbols as a sequence of bytes. /// @@ -578,7 +607,7 @@ mod huffman { } /// Decoder - #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Default)] + #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Default, Clone)] pub enum Decode { /// An as-yet unfilled slot. #[default] diff --git a/src/impls/option.rs b/src/impls/option.rs index 608e003..b56b6c2 100644 --- a/src/impls/option.rs +++ b/src/impls/option.rs @@ -25,12 +25,24 @@ impl Containerized for Option { /// assert_eq!(Some(123), r.index(some_index)); /// assert_eq!(None, r.index(none_index)); /// ``` -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct OptionRegion { inner: R, } +impl Clone for OptionRegion { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner); + } +} + impl Region for OptionRegion { type Owned = Option; type ReadItem<'a> = Option<::ReadItem<'a>> where Self: 'a; diff --git a/src/impls/result.rs b/src/impls/result.rs index 05301c5..5a26670 100644 --- a/src/impls/result.rs +++ b/src/impls/result.rs @@ -25,13 +25,27 @@ impl Containerized for Result { /// assert_eq!(Ok(()), r.index(ok_index)); /// assert_eq!(Err("Error"), r.index(err_index)); /// ``` -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ResultRegion { oks: T, errs: E, } +impl Clone for ResultRegion { + fn clone(&self) -> Self { + Self { + oks: self.oks.clone(), + errs: self.errs.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.oks.clone_from(&source.oks); + self.errs.clone_from(&source.errs); + } +} + impl Region for ResultRegion where T: Region, diff --git a/src/impls/slice.rs b/src/impls/slice.rs index 8d38b6d..8bd4ef4 100644 --- a/src/impls/slice.rs +++ b/src/impls/slice.rs @@ -51,7 +51,7 @@ impl Containerized for [T; N] { /// /// assert_eq!(r.index(de_index).get(2), "jagen"); /// ``` -#[derive(Debug, Clone)] +#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct SliceRegion = Vec<::Index>> { /// Container of slices. @@ -60,6 +60,24 @@ pub struct SliceRegion = Vec< Clone for SliceRegion +where + R: Region + Clone, + O: OffsetContainer + Clone, +{ + fn clone(&self) -> Self { + Self { + slices: self.slices.clone(), + inner: self.inner.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.slices.clone_from(&source.slices); + self.inner.clone_from(&source.inner); + } +} + impl> Region for SliceRegion { type Owned = Vec; type ReadItem<'a> = ReadSlice<'a, C, O> where Self: 'a; diff --git a/src/impls/slice_copy.rs b/src/impls/slice_copy.rs index 6229dfc..33aa134 100644 --- a/src/impls/slice_copy.rs +++ b/src/impls/slice_copy.rs @@ -27,12 +27,24 @@ use crate::{CopyIter, Push, Region, ReserveItems}; /// assert_eq!(panagram_de.as_bytes(), r.index(de_index)); /// assert_eq!(panagram_en.as_bytes(), r.index(en_index)); /// ``` -#[derive(Debug, Clone)] +#[derive(Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct OwnedRegion { slices: Vec, } +impl Clone for OwnedRegion { + fn clone(&self) -> Self { + Self { + slices: self.slices.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.slices.clone_from(&source.slices); + } +} + impl Region for OwnedRegion where [T]: ToOwned, diff --git a/src/impls/string.rs b/src/impls/string.rs index 1403b88..9b700ea 100644 --- a/src/impls/string.rs +++ b/src/impls/string.rs @@ -30,7 +30,7 @@ use crate::{Containerized, Push, Region, ReserveItems}; /// assert_eq!(panagram_de, r.index(de_index)); /// assert_eq!(panagram_en, r.index(en_index)); /// ``` -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct StringRegion> where @@ -39,6 +39,21 @@ where inner: R, } +impl Clone for StringRegion +where + for<'a> R: Region = &'a [u8]> + Clone + 'a, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner); + } +} + impl Region for StringRegion where for<'a> R: Region = &'a [u8]> + 'a, diff --git a/src/impls/tuple.rs b/src/impls/tuple.rs index 23181e4..17502df 100644 --- a/src/impls/tuple.rs +++ b/src/impls/tuple.rs @@ -16,12 +16,28 @@ macro_rules! tuple_flatcontainer { /// A region for a tuple. #[allow(non_snake_case)] - #[derive(Default, Clone, Debug)] + #[derive(Default, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct []<$($name),*> { $([]: $name),* } + #[allow(non_snake_case)] + impl<$($name: Region + Clone),*> Clone for []<$($name),*> + where + $(<$name as Region>::Index: crate::Index),* + { + fn clone(&self) -> Self { + Self { + $([]: self.[].clone(),)* + } + } + + fn clone_from(&mut self, source: &Self) { + $(self.[].clone_from(&source.[]);)* + } + } + #[allow(non_snake_case)] impl<$($name: Region),*> Region for []<$($name),*> where diff --git a/src/lib.rs b/src/lib.rs index fbd7bbc..04f67ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -359,6 +359,11 @@ impl Clone for FlatStack { indices: self.indices.clone(), } } + + fn clone_from(&mut self, source: &Self) { + self.region.clone_from(&source.region); + self.indices.clone_from(&source.indices); + } } /// A type to wrap and copy iterators onto regions.