From f66bcc5459d4a720b31eaeac3149f19799118d72 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sat, 20 Jun 2020 11:07:22 +0800 Subject: [PATCH] Add liballoc impl SpecFromElem for i8 Speedup vec![1_i8; N] for non-zero element. Before test do_bench_from_elem_i8 ... bench: 130 ns/iter (+/- 7) = 61 MB/s test do_bench_from_elem_u8 ... bench: 121 ns/iter (+/- 4) = 66 MB/s After test do_bench_from_elem_i8 ... bench: 123 ns/iter (+/- 7) = 65 MB/s test do_bench_from_elem_u8 ... bench: 121 ns/iter (+/- 5) = 66 MB/s No speed difference if element is already zero. #[bench] fn do_bench_from_elem_i8(b: &mut Bencher) { b.bytes = 8 as u64; b.iter(|| { let dst = ve::vec![10_i8; 100]; assert_eq!(dst.len(), 100); assert!(dst.iter().all(|x| *x == 10)); }) } As suggested by @cuviper https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/SpecForElem.20for.20other.20integers --- src/liballoc/vec.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index f16cac05ea039..b4a8597656ecb 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1803,6 +1803,21 @@ impl SpecFromElem for T { } } +impl SpecFromElem for i8 { + #[inline] + fn from_elem(elem: i8, n: usize) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed(n), len: n }; + } + unsafe { + let mut v = Vec::with_capacity(n); + ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); + v.set_len(n); + v + } + } +} + impl SpecFromElem for u8 { #[inline] fn from_elem(elem: u8, n: usize) -> Vec { @@ -1847,7 +1862,6 @@ macro_rules! impl_is_zero { }; } -impl_is_zero!(i8, |x| x == 0); impl_is_zero!(i16, |x| x == 0); impl_is_zero!(i32, |x| x == 0); impl_is_zero!(i64, |x| x == 0);