[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
collect
ing 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
TryFromIterator
trait (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 Vec
tors (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:
-
Vec
is 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
stackvec
improves 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"stackvec
using the following line instead:= { = "0.2.1", = false }
- Note: By default
-
Add this to your
.rs
code:extern crate stackvec; use *;
Examples
See the source files for the examples
You can run each example (example_name.rs
) with: