rust: impl TrustedLen for VectorIter (#8797)
Improves unpack performance for vectors by allowing the compiler
to vectorize flatbuffers::Vector to std::vec::Vec conversions,
using the unstable trusted_len feature.
Internally, enables an optimization in src/alloc/vec/spec_extend.rs:
Previously, unpacking a flatbuffers::Vector called
SpecExtend::extend_desugared fallback, which inhibits vectorization
(due to a branch before every element move). Declaring TrustedLen
allows SpecExtend::extend_trusted, which LLVM can often vectorize
into a memcpy.
For [ubyte] vectors in particular, this turns a rather expensive
loop of 'mov BYTE PTR [rax+r13*1], bpl' into a `call memcpy`.
diff --git a/rust/flatbuffers/src/lib.rs b/rust/flatbuffers/src/lib.rs
index 600d6d9..ed2bc17 100644
--- a/rust/flatbuffers/src/lib.rs
+++ b/rust/flatbuffers/src/lib.rs
@@ -30,6 +30,7 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(all(nightly, not(feature = "std")), feature(error_in_core))]
+#![cfg_attr(nightly, feature(trusted_len))]
#[cfg(not(feature = "std"))]
extern crate alloc;
diff --git a/rust/flatbuffers/src/vector.rs b/rust/flatbuffers/src/vector.rs
index 6c559b4..2078a76 100644
--- a/rust/flatbuffers/src/vector.rs
+++ b/rust/flatbuffers/src/vector.rs
@@ -17,6 +17,8 @@
use core::cmp::Ordering;
use core::fmt::{Debug, Formatter, Result};
use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator};
+#[cfg(nightly)]
+use core::iter::TrustedLen;
use core::marker::PhantomData;
use core::mem::{align_of, size_of};
use core::str::from_utf8_unchecked;
@@ -293,6 +295,9 @@
}
}
+#[cfg(nightly)]
+unsafe impl<'a, T: Follow<'a> + 'a> TrustedLen for VectorIter<'a, T> {}
+
impl<'a, T: 'a + Follow<'a>> FusedIterator for VectorIter<'a, T> {}
impl<'a, T: Follow<'a> + 'a> IntoIterator for Vector<'a, T> {