13个不稳定版本 (6个重大更改)
0.7.2 | 2024年3月24日 |
---|---|
0.7.1 | 2023年11月29日 |
0.6.0 | 2023年11月22日 |
0.5.1 | 2023年1月10日 |
0.5.0 | 2022年11月18日 |
#712 in 数据结构
用于 rl_ball_sym
63KB
657 行
combo_vec
ComboVec
用于创建一个 "组合栈数组-堆向量",或者简单地说是一个可调整大小的数组,其中包含一个用于额外分配的向量。
不仅如此,如果只想使用可调整大小的数组部分,这个库还提供了 ReArr
。
使用 combo_vec!
宏创建一个新的 ComboVec
,并使用 re_arr!
宏创建一个新的 ReArr
。
这是通过在栈上分配一个 T
数组来实现的,然后使用堆上的 Vec 处理溢出。
即使数组被调整大小,栈分配的数组也始终用于存储前 N
个元素。
不需要 为 T
实现 Default
、Copy
或 Clone
特性;但如果 T 实现了其中任何一个,则 ComboVec
和 ReArr
也会实现它们。这也适用于 PartialEq
、PartialOrd
、Eq
、Ord
、Hash
、Debug
和 Display
。
为什么使用ComboVec
这主要用于当您知道99%的情况下将要存储的元素的最大数量,但又不想在最后1%时引起错误,同时也不会放弃使用栈而不是堆的大部分性能。
我在 ComboVec
上获得了性能提升,与类似的类型 SmallVec(带有和没有它的 union
功能)相比。
在测试推送2048(预分配)个元素时,性能提高了近54%
ComboVec
:4.54 µsSmallVec
:9.33 µs
combo_vec!
宏非常方便使用,甚至在 const 上下文中也很方便。
use combo_vec::{combo_vec, ComboVec};
const SOME_ITEMS: ComboVec<i8, 3> = combo_vec![1, 2, 3];
const MANY_ITEMS: ComboVec<u16, 90> = combo_vec![5; 90];
const EXTRA_ITEMS: ComboVec<&str, 5> = combo_vec!["Hello", "world", "!"; None, None];
// Infer the type and size of the ComboVec
const NO_STACK_F32: ComboVec<f32, 0> = combo_vec![];
// No const-initialization is needed to create a ComboVec with allocated elements on the stack
use std::collections::HashMap;
const EMPTY_HASHMAP_ALLOC: ComboVec<HashMap<&str, i32>, 3> = combo_vec![];
// Creating a new ComboVec at compile time and doing this does have performance benefits
let my_combo_vec = EMPTY_HASHMAP_ALLOC;
ComboVec
还实现了许多仅限于 Vec
的方法,例如 extend
、truncate
、push
、join
等。
为什么使用 ReArr
在测试推送2048(预分配)个元素时,其性能与 ArrayVec
相当
ReArr
:4.07 µsArrayVec
:4.00 µs
re_arr!
宏非常方便使用,即使在 const 上下文中也很方便。
use combo_vec::{re_arr, ReArr};
const SOME_ITEMS: ReArr<i8, 3> = re_arr![1, 2, 3];
const MANY_ITEMS: ReArr<u16, 90> = re_arr![5; 90];
const EXTRA_ITEMS: ReArr<&str, 5> = re_arr!["Hello", "world", "!"; None, None];
// Infer the type and size of the ReArr
const NO_STACK_F32: ReArr<f32, 0> = re_arr![];
// No const-initialization is needed to create a ComboVec with allocated elements on the stack
use std::collections::HashMap;
const EMPTY_HASHMAP_ALLOC: ReArr<HashMap<&str, i32>, 3> = re_arr![];
// Creating a new ReArr at compile time and doing this does have performance benefits
let my_re_arr = EMPTY_HASHMAP_ALLOC;
ReArr
还实现了许多仅限于 Vec
的方法,例如 extend
、truncate
、push
、join
等。
示例
快速查看一个基本示例和一些可用方法
use combo_vec::combo_vec;
let mut combo_vec = combo_vec![1, 2, 3];
// Allocate an extra element on the heap
combo_vec.push(4);
// Truncate to a length of 2
combo_vec.truncate(2);
// Fill the last element on the stack, then allocate the next items on the heap
combo_vec.extend([3, 4, 5]);
在栈上分配空内存
您可以在栈上分配内存供以后使用,而无需设置其值!
不需要 Copy 或 Default 特性。
use combo_vec::{combo_vec, re_arr};
// Allocate a new space to store 17 elements on the stack.
let empty_combo_vec = ComboVec::<f32, 17>::new();
let empty_re_arr = ReArr::<f32, 17>::new();
在 const 上下文中在栈上分配内存
使用 combo_vec!
/re_arr!
宏的主要优点是,它可以用于 const 上下文中。
这允许您在程序开始时在 Mutex 或 RwLock 中分配一个 ComboVec,从而具有最小的运行时开销。
use combo_vec::{combo_vec, ComboVec, re_arr, ReArr};
// Create a global variable for the various program states for a semi-unspecified length
use std::{collections::HashMap, sync::RwLock};
static PROGRAM_STATES: RwLock<ComboVec<HashMap<String, i32>, 20>> = RwLock::new(combo_vec![]);
// If we know the stack will never be larger than 20 elements,
// we can get a performance boost by using ReArr instead of ComboVec
let mut runtime_stack = ReArr::<i32, 20>::new();
使用 const & copy 快速运行
我们可以通过创建一个 const 上下文然后将其复制到我们的运行时变量中,来利用 ComboVec
和 ReArr
。这比在运行时创建一个新的 ComboVec
快得多,而且 T
不需要是 Copy
。
以下是这个示例的基本看法
use combo_vec::{combo_vec, ComboVec};
const SOME_ITEMS: ComboVec<String, 2> = combo_vec![];
for _ in 0..50 {
let mut empty_combo_vec = SOME_ITEMS;
empty_combo_vec.push("Hello".to_string());
empty_combo_vec.push("world".to_string());
println!("{}!", empty_combo_vec.join(" "));
}