"combo_vec" is a library for creating a "combo stack array-heap vector", or simply a resizable array.
Create a new ReArr
with the rearr!
macro.
This works by allocating an array of T
on the stack, and then using a Vec on the heap for overflow.
The stack-allocated array is always used to store the first N
elements, even when the array is resized.
This is mostly used for when you know the maximum number of elements that will be stored 99% if the time, but don't want to cause errors in the last 1% and also won't want to give up on the performance of using the stack instead of the heap most of the time.
ReArr
also implemented many methods that are exclusive to Vec
such as extend
, truncate
, push
, join
etc.
In the real world I've seen a performance increase by using ReArr
over Vec
on memory-bandwidth limited devices in situations where the Vec
is being pushed and popped a lot from. I found this performance increase and use ReArr
in the rl_ball_sym
crate for this performance bump.
A quick look at a basic example and some methods that are available:
```rust use combo_vec::rearr;
let mut resizeablevec = rearr![1, 2, 3]; // Allocate an extra element on the heap resizeablevec.push(4); // Truncate to only the first 2 elements resizeablevec.truncate(2); // Fill the last element on the stack, then allocate the next two items on the heap resizeablevec.extend([3, 4, 5]); ```
You can allocate memory on the stack for later use without settings values to them!
No Copy or Default traits required.
```rust use combo_vec::rearr;
// Easily allocate a new ReArr where 16 elements can be stored on the stack. let defaultf32vec = rearr![f32];
// Allocate a new, empty ReArr with 17 elements abled to be stored on the stack. let emptyf32vec = rearr![f32; 17]; ```
The main benefit of using the rearr!
macro is that everything it does can be used in const contexts.
This allows you to allocate a ReArr at the start of your program in a Mutex or RwLock, and have minimal runtime overhead.
```rust use combo_vec::{rearr, ReArr};
const SOMEITEMS: ReArr
// Infer the type and size of the ReArr
const NOSTACKF32: ReArr
// No const default implementation is needed to create a ReArr with allocated elements on the stack
use std::collections::HashMap;
const EMPTYHASHMAPALLOC: ReArr
/// Create a global-state RwLock that can store a ReArr
use std::sync::RwLock;
static PROGRAM_STATE: RwLock
Making an entire, new ReArr
at runtime can be slower than just allocating a new array or a new vector - because it needs to do both.
We can take advantage of ReArr
being a Copy
type, and use it to create a new ReArr
in a const context then copy it to our runtime variable. This is much faster than creating a new ReArr
at runtime. T
does not need to be Copy
.
Here's a basic look at what this looks like:
```rust use combo_vec::{rearr, ReArr};
const SOME_ITEMS: ReArr
for _ in 0..5 { let mut emptyrearr = SOMEITEMS; emptyrearr.push("Hello".tostring()); emptyrearr.push("World".tostring()); println!("{}!", empty_rearr.join(" ")); } ```