[stack;vec]
A rust crate to use stack-allocated vectors (to improve performance and/or when there is no std)
Motivation
Rust stack/inline arrays don't implement 2 very useful iterator-related interfaces:
-
IntoIterator<Item = T> for [T; n]- Allows using
.into_iter()instead of.iter().cloned()(which, by the way, can only be used whenT: Clone, and requires cloning, which may be expensive) -
extern crate stackvec; use *;
- Allows using
-
FromIterator for [T; n]- Allows
collecting into anarray - Since it is unsound to have an incomplete array, the collecting fails when the iterator does not have enough elements to fill the array. Hence the new
TryFromIteratortrait (providingtry_collect). -
extern crate stackvec; use *;
- Allows
The reason for that is that both interfaces need a structure being able to hold
the partially iterated state: i.e., incomplete arrays. Those have (statically-allocated) memory that might not be initialized: so they are, in a way, like Vectors (except for the fact that their (initial) capacity is fixed and cannot be changed)
That's why having those nice iterator interfaces requires writing down a slot-accurate memory ownership management logic very similar to Vec's : hence the StackVec.
Bonus
By exposing the underlying StackVec needed by the aformentioned interfaces, we get full access to a stack-allocated Vec, which can also be useful on its own, since it avoids heap allocation:
-
the heap is a mutable global state and in multi-threaded environments locks are involved,
-
it may require (slow) system allocation
Disclaimer
The performance gain (from using StackVec instead of Vec) is not always guaranteed, since:
-
Vecis the cornerstone of Rust's std library collection and has extremely efficient code written so that LLVM can easily optimize its usage -
Rust's allocator is also incredibly well optimised so the performance penalties from bins management and system allocations (and the locks in a multi-threaded environment) are quite well amortized on average.
Vec vs StackVec basic benchmark
)
)
)
)
)
)
)
Usage
-
Add this line to your
Cargo.toml(under[dependencies]):= "0.2.1"- Note: By default
stackvecimproves all the arrays with less than 1000 elements. This leads to longer compilation times. If this is an issue, and you don't really plan on using arbitrary-length arrays but at fixed multiples of 100 or powers of 2, you can depend on a "lighter"stackvecusing the following line instead:= { = "0.2.1", = false }
- Note: By default
-
Add this to your
.rscode:extern crate stackvec; use *;
Examples
See the source files for the examples
You can run each example (example_name.rs) with: