3次发布
0.1.2 | 2024年7月7日 |
---|---|
0.1.1 | 2024年7月7日 |
0.1.0 | 2024年7月6日 |
在数据结构中排名588
每月下载345次
15KB
224 行
一个3指针迭代器,可以从Vec<T>
或Box<[T]>
中移出数据
为什么?
如果您想迭代并从Vec<T>
中移出项,您通常会调用.into_iter()
,生成一个vec::IntoIter
迭代器。(注意:即将到来的Box<[T]>
的IntoIterator
实现也使用vec::IntoIter
。)这对于大多数用例来说是可以的。
然而,存储大量vec::IntoIter
迭代器可能对内存使用来说不是最优的。这是因为vec::IntoIter
被表示为4个指针,这比仅用于单方向迭代时严格必要的多一个。
此crate提供了一个SmallIter
类型,它被表示为3个指针。为了换取更小的尺寸,此类型不实现DoubleEndedIterator
。
用法
IntoSmallIterExt
特质提供了into_small_iter()
方法,它允许您从Vec<T>
或Box<[T]>
生成SmallIter
迭代器。
use small_iter::IntoSmallIterExt;
let v = vec![1, 2, 3];
let iter = v.into_small_iter();
let v2: Vec<_> = iter.collect();
assert_eq!(v2, vec![1, 2, 3]);
此crate节省空间的好处可能仅在您存储大量迭代器时相关。
use small_iter::{IntoSmallIterExt, SmallIter};
let v = vec![vec![1, 2], vec![3, 4], vec![5, 6]];
let mut iters: Vec<SmallIter<i32>> = v.into_iter().map(|v| v.into_small_iter()).collect();
assert_eq!(iters[0].next(), Some(1));
assert_eq!(iters[1].next(), Some(3));
assert_eq!(iters[2].next(), Some(5));
assert_eq!(iters[0].next(), Some(2));
assert_eq!(iters[1].next(), Some(4));
assert_eq!(iters[2].next(), Some(6));
注意
对于Vec<T>
,如果向量化器中存在剩余容量,调用into_small_iter
将首先缩小分配以适应现有元素。根据分配器,这可能会导致重新分配。
另一方面,在Box<[T]>
上调用into_small_iter
是廉价的。
基准测试结果
我在Macbook Pro 2021上对以下工作负载进行了基准测试(这是该crate预期的工作负载类型):构建10万个迭代器,每个迭代器包含100个u8
。然后,获取每个迭代器的第一个元素,然后是第二个,依此类推。
此工作负载以三种方式进行
- 使用
SmallIter
(此crate)- 平均耗时20.4毫秒
- 使用来自
thin-vec
crate的thin_vec::IntoIter
- 平均耗时30.5毫秒
- 使用
std::vec::IntoIter
- 平均耗时21.9毫秒
基准测试的源代码可以在这里找到。