5 个不稳定版本
使用旧的 Rust 2015
0.2.1 | 2018 年 11 月 11 日 |
---|---|
0.1.1 | 2018 年 11 月 4 日 |
0.1.0 | 2018 年 11 月 4 日 |
0.0.2 | 2018 年 11 月 1 日 |
0.0.1 | 2018 年 10 月 28 日 |
2520 在 Rust 模式 中排名
每月 117 次下载
3MB
850 行
包含 (ELF 可执行文件/库, 7.5MB) kcov/kcov, (ELF 库, 1MB) kcov/libbfd-2.25-system.so, (ELF 库, 1.5MB) kcov/libopcodes-2.25-system.so
[栈;向量]
一个 Rust crate,用于使用栈分配向量(以提高性能或在没有 std 的情况下使用)
动机
Rust 的 栈/内联数组 没有实现 2 个非常有用的与 迭代器相关 的 接口
-
IntoIterator<Item = T> for [T;n]
- 允许使用
.into_iter()
代替.iter().cloned()
(实际上,只能在T: Clone
的情况下使用,并且需要复制,这可能会很昂贵) -
extern crate stackvec; use ::stackvec::prelude::*; fn main () { // An array of vectors (potentially expensive to clone) let vecs_array = [ vec![1, 2, 3, 4], vec![], vec![5, 6], ]; // Collect / chain all the vectors together let flattened: Vec<u8> = vecs_array .into_iter() // Needs stackvec (line 1) .flatten() .collect() ; assert_eq!(flattened, vec![1, 2, 3, 4, 5, 6]); }
- 允许使用
-
FromIteratorfor [T;n]
- 允许将
collect
收集到array
- 由于不完整的数组是不可靠的,当迭代器没有足够的元素填充数组时,收集会失败。因此,引入了新的
TryFromIterator
特性(提供try_collect
)。 -
extern crate stackvec; use ::stackvec::prelude::*; fn main () { let array: [_; 3] = [1, 2, 3]; let doubled: [_; 3] = array .iter() .map(|&x| 2 * x) .try_collect() // Needs stackvec (line 1) .expect("Missing elements to collect") ; assert_eq!(doubled, [2, 4, 6]); }
- 允许将
原因在于这两个接口都需要一个能够存储部分迭代状态的结构:即不完整的数组。它们具有(静态分配的)可能未初始化的内存:因此,它们在某种程度上类似于 Vec
(除了它们的(初始)容量是固定的且不能更改之外)
这就是为什么拥有那些优秀的迭代器 接口需要编写一个与Vec
'的内存所有权管理逻辑非常相似的插槽精确逻辑:因此才有StackVec
。
附加说明
通过公开上述接口所需的底层StackVec
,我们能够完全访问一个堆栈分配的Vec
,它本身也可能很有用,因为它避免了堆分配
-
堆是一个可变的全局状态,在多线程环境中涉及锁
-
它可能需要(缓慢的)系统分配
免责声明
使用StackVec
而不是Vec
带来的性能提升并不总是保证,因为
-
Vec
是Rust std库集合的基石,其代码被编写得非常高效,以便LLVM可以轻松优化其使用 -
Rust的分配器也进行了非常出色的优化,因此bins管理和系统分配(以及在多线程环境中的锁)的性能惩罚在平均情况下得到了很好的摊销。
Vec
与StackVec
基本基准测试
$ cargo +nightly bench --features nightly
test vec_extend ... bench: 64,129 ns/iter (+/- 3,069)
test vec_from_iter ... bench: 65,569 ns/iter (+/- 3,761)
test array_from_iter ... bench: 358,993 ns/iter (+/- 6,916)
test stackvec_extend ... bench: 360,105 ns/iter (+/- 17,489)
test stackvec_from_iter ... bench: 369,585 ns/iter (+/- 40,894)
test stackvec_extend_by_ref ... bench: 374,226 ns/iter (+/- 11,686)
test vec_extend_by_ref ... bench: 863,362 ns/iter (+/- 32,483)
使用方法
-
将此行添加到您的
Cargo.toml
(在[dependencies]
下)stackvec = "0.2.1"
- 注意:默认情况下,
stackvec
改进所有小于1000个元素的数组。这会导致编译时间更长。如果这是一个问题,并且您并不真的打算使用任意长度的数组,而是使用100的固定倍数或2的幂,您可以使用以下行依赖一个“更轻”的stackvec
stackvec = { version = "0.2.1", default-features = false }
- 注意:默认情况下,
-
将此添加到您的
.rs
代码extern crate stackvec; use ::stackvec::prelude::*;
示例
查看示例的源代码(链接)
您可以使用以下命令运行每个示例(example_name.rs
)
$ cargo run --example example_name