展平收片效率
Efficiency of flattening and collecting slices
如果在 Iterator<Item=&[T]> where T: Copy
上使用标准 .flatten().collect::<Box<[T]>>()
,是否:
- 执行单次分配;和
- 使用
memcpy
将每个项目复制到目的地
还是它做了一些效率较低的事情?
Box<[T]>
没有实现 FromIterator<&T>
,所以我假设你的实际内部迭代器是产生拥有的 T
s.
的东西
FromIterator<T>
for Box<[T]>
forwards to Vec<T>
, which uses size_hint()
为 lower
+ 1 项目保留 space,并在超出该项目时重新分配(根据需要移动元素).所以问题是,Flatten<I>
return 对于 size_hint
是什么?
Iterator::size_hint
的实施 Flatten<I>
forwards to the internal struct FlattenCompat<I>
, which is a little complicated because it supports double-ended iteration, but ultimately returns (0, None)
if the outer iterator has not been advanced or exhausted。
所以你的问题的答案是:它做了一些效率较低的事情。即,(除非您已经在迭代器上至少调用过 next
或 next_back
一次)它会创建一个空的 Vec<T>
并根据 Vec
使用的任何增长策略逐步增长它(未指定,但 guaranteed by the documentation to result in O(1)
amortized push
)。
这不是人为限制;它是 Flatten
工作方式的基础。预先计算展平迭代器大小的唯一方法是用尽外部迭代器并将所有内部 size_hint
相加。这是一个坏主意,因为它并不总是有效(内部迭代器可能 return 没有用 size_hint
s),而且你还必须找到一种方法来在耗尽外面的;没有通用迭代器适配器可接受的解决方案。
如果您对特定迭代器有所了解,可以知道最终大小应该是多少,您可以通过调用 Vec::with_capacity
自己保留分配并使用 Extend
从flatten
ed 迭代器,而不是使用 collect
.
如果在 Iterator<Item=&[T]> where T: Copy
上使用标准 .flatten().collect::<Box<[T]>>()
,是否:
- 执行单次分配;和
- 使用
memcpy
将每个项目复制到目的地
还是它做了一些效率较低的事情?
Box<[T]>
没有实现 FromIterator<&T>
,所以我假设你的实际内部迭代器是产生拥有的 T
s.
FromIterator<T>
for Box<[T]>
forwards to Vec<T>
, which uses size_hint()
为 lower
+ 1 项目保留 space,并在超出该项目时重新分配(根据需要移动元素).所以问题是,Flatten<I>
return 对于 size_hint
是什么?
Iterator::size_hint
的实施 Flatten<I>
forwards to the internal struct FlattenCompat<I>
, which is a little complicated because it supports double-ended iteration, but ultimately returns (0, None)
if the outer iterator has not been advanced or exhausted。
所以你的问题的答案是:它做了一些效率较低的事情。即,(除非您已经在迭代器上至少调用过 next
或 next_back
一次)它会创建一个空的 Vec<T>
并根据 Vec
使用的任何增长策略逐步增长它(未指定,但 guaranteed by the documentation to result in O(1)
amortized push
)。
这不是人为限制;它是 Flatten
工作方式的基础。预先计算展平迭代器大小的唯一方法是用尽外部迭代器并将所有内部 size_hint
相加。这是一个坏主意,因为它并不总是有效(内部迭代器可能 return 没有用 size_hint
s),而且你还必须找到一种方法来在耗尽外面的;没有通用迭代器适配器可接受的解决方案。
如果您对特定迭代器有所了解,可以知道最终大小应该是多少,您可以通过调用 Vec::with_capacity
自己保留分配并使用 Extend
从flatten
ed 迭代器,而不是使用 collect
.