我的应用程序包含一个定制的RingBuffer实现,因为我需要 一些VecDeque<u8>没有提供的功能.

对我来说,性能关键路径是使用该环形缓冲器的子范围到达extendaVec<u8>.因此,我进行了基准测试,发现默认的VecDeque range ITER的性能明显好于我的,尽管数据 struct 几乎相同.

I checked in godbolt,正如预期的那样,内置的一款获得了很酷的自动矢量化,而我的一款则没有.

虽然我可能会结束为我的用例编写手册extend_from_slice / std::ptr::copy, 我很想知道是否有什么我可以做的事情来获得与内置迭代器相当的性能.到目前为止,我try 使用&u8的iter,但这是更糟糕的.

有没有什么我可以为我的Iter或其他东西实现的额外特性?

我的代码如下所示:

use std::collections::VecDeque;

pub struct RingbufIter<'a> {
    s1: std::slice::Iter<'a, u8>,
    s2: std::slice::Iter<'a, u8>,
}
impl<'a> Iterator for RingbufIter<'a> {
    type Item = u8;
    fn next(&mut self) -> Option<Self::Item> {
        match self.s1.next().copied() {
            Some(b) => Some(b),
            None => {
                // swap to reduce branches on subsequent `next` calls
                std::mem::swap(&mut self.s1, &mut self.s2);
                self.s1.next().copied()
            }
        }
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (s1_min, s1_max) = self.s1.size_hint();
        let (s2_min, s2_max) = self.s2.size_hint();
        (s1_min + s2_min, Some(s1_max.unwrap() + s2_max.unwrap()))
    }
}

#[no_mangle]
pub fn extend_from_custom_iter(src: RingbufIter, sink: &mut Vec<u8>)  {
    sink.extend(src)
}

#[no_mangle]
pub fn extend_from_vec_deque(src: &mut VecDeque<u8>, sink: &mut Vec<u8>)  {
    sink.extend(src.range(0..src.len()))
}

推荐答案

标准库使用专门化为其已知的某些集合提供更快的Extend实现.但是它不稳定,所以不能用.如果要手动实现Extend,new type也可以.否则,只需编写普通方法RingbufIter::extend_into_vec(&mut self, &mut Vec<u8>)即可.例如:

#[no_mangle]
pub fn extend_from_custom_iter(src: RingbufIter, sink: &mut Vec<u8>)  {
    // Write optimized version that copies slices here
    // instead of relying on `Vec as Extend`.
}

不幸的是,这将阻止您编写泛型代码,但如果您的用例是只使用自定义环形缓冲区和Vec,这应该是好的.

编辑.实际上,使用新类型并为其实现Extend是不可能的,因为Extend::extend在其扩展的迭代器上是generic.因此,要对RingbufIter使用专门的算法,您必须使用另一个特征SpecializedExtend,并为RingbufIter实现它,并为all other个迭代器提供空白实现,这是STD在内部所做的,也是不稳定的.所以你必须使用具体的实现方法.

Rust相关问答推荐

如何找到一个数字在二维数组中的位置(S)?

使用Clap时如何将String作为Into Str参数传递?

定义采用更高级类型泛型的性状

无法将记录器向下转换回原始 struct

如何指定不同的类型来常量Rust中的泛型参数?

避免在Collect()上进行涡鱼类型的涂抹,以产生<;Vec<;_>;,_>;

正则表达式中的重叠匹配?(铁 rust 正则式发动机)

装箱特性如何影响传递给它的参数的生命周期 ?(举一个非常具体的例子)

为什么 GAT、生命周期和异步的这种组合需要 `T: 'static`?

Rust,如何从 Rc> 复制内部值并返回它?

为什么某些类型参数仅在特征边界中使用的代码在没有 PhantomData 的情况下进行编译?

一次不能多次borrow *obj作为可变对象

unwrap 选项类型出现错误:无法移出共享引用后面的*foo

部署Rust发布二进制文件的先决条件

为什么可以在迭代器引用上调用 into_iter?

为什么1..=100返回一个范围而不是一个整数?

我如何将 google_gmail1::Gmail> 传递给线程生成?

Rust 跨同一文件夹中文件的可见性

当用作函数参数时,不强制执行与绑定的关联类型

在 Rust 中获得准确时间的正确方法?