使用 clone_from_slice() 而不是 copy_from_slice() 的性能损失?

Ber*_*ard 3 performance clone copy rust

在 Rust 中,有两种方法可以从另一个切片更新切片的内容:clone_from_slice()copy_from_slice(). 这两个函数的行为并不奇怪 - 第一个执行克隆并期望类型实现Clone,而第二个执行复制并期望类型实现Copy

然而,令我惊讶的是,它的文档是这样clone_from_slice说的:“如果T实现了Copy,使用它可以提高性能copy_from_slice。” 令人惊讶的是,这里应该存在性能差异。如果Timplements Copy,则.clone()要求相当于复制位;但是,由于编译器知道是什么类型T,因此即使我使用clone_from_slice.

那么性能低效从何而来?

Öme*_*den 5

TL;DR 请检查clone_from_slice的来源,它是访问 slice 的所有元素并调用clone每个元素,而copy_from_slice直接复制所有位memcpy


如果 T 实现Copy,则.clone()需要等效于复制位

即使每个Copy类型都会Clone默认实现whereclone直接使用copy; clone_from_slice仍然会遍历切片并在遍历时进行复制。

但是没有这个命题对于原语是正确的,但对于以下情况不正确

#[derive(Copy)]
struct X;

impl Clone for X {
    fn clone(&self) -> Self {
        //do some heavy operation or light(depends on the logic)

        X
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然Clone可以由任何逻辑Copy类型实现,但在复制对象时只会复制位。

如果 T 实现Copy,则使用它可以提高性能copy_from_slice

重要的是在这里,文档说“它可以”不是“它会是”,这带来了像

  • Cloneimplementation 可以直接使用Copyimplementation。对于基本类型如原语,优化器可能会直接使用memcpy而不是遍历,那么我们可能会认为这个命题是错误的,因为一个不会比另一个更好。

  • Cloneimplementation 可以直接使用Copyimplementation。对于复杂类型(上面的遍历问题),这个命题是正确的。(我用更复杂的结构编辑了@kmdreko的例子请检查 Godbolt 的结果

  • Clone实现是自定义的并且它是一种Copy类型,即使自定义实现不昂贵,这将使这个命题正确,然后copy对于大切片使用memcpy可能更有益。