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

标签 performance rust copy clone

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

然而,令我惊讶的是 clone_from_slice 的文档是这样说的:“如果 T 实现了 Copy,它的使用性能会更高copy_from_slice。”令人惊讶的是,这里应该存在性能差异。如果T实现了Copy,则要求.clone()等同于复制位;然而,由于编译器知道 T 是什么类型,它应该能够确定它是否可以进行按位复制,即使我使用 clone_from_slice

那么性能低下的原因是什么?

最佳答案

TL;DR 请检查 clone_from_slice 的来源, 它正在访问 slice 的所有元素并调用 clone对于每个,同时 copy_from_slice直接用 memcpy 复制所有位.

注意:对于 Rust 版本 1.52.0clone_from_slice通过 specialization 实现, 如果你调用 clone_from_sliceCopy它将调用的类型 copy_from_slice在内部。 ( reference )


If T implements Copy, then .clone() is required to be equivalent to copying bits

即使每 Copy类型将实现 Clone默认情况下 clone直接使用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
    }
}

同时 Clone可以通过任何逻辑实现Copy复制对象时,类型将简单地复制位。

If T implements Copy, it can be more performant to use copy_from_slice

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

这样的可能性
  • Clone实现可以直接用Copy执行。对于基元等基本类型,优化器可以直接使用memcpy而不是遍历,那么我们可能会接受这个命题是错误的,因为一个人不会比另一个人表现更好。

  • Clone实现可以直接用Copy执行。对于复杂类型(上面的遍历问题)使这个命题正确。 (我编辑了来自@kmdreko 的 example,结构有点复杂,please check the result from godbolt)

  • Clone实现是自定义的,它是一个 Copy类型,这个将使这个命题正确,即使自定义实现很便宜 copy对于大切片使用 memcpy可能更有益。

关于使用 clone_from_slice() 而不是 copy_from_slice() 的性能损失?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63426583/

相关文章:

mysql - GROUP_CONCAT 不同查询和子查询的性能问题

JavaScript:在循环内优化循环

rust - 是否可以匹配 `const fn` 的结果?

ios - swift 启用使用 copy() 或 unshare method()

c# - 将目录复制到输出目录 - 控制台应用程序 .NET

VBA将文件从一个目录复制到另一个目录

excel - 在获取 Excel 工作簿中所有工作表名称的列表期间,VBA 代码的执行速度非常慢

javascript - 如何优化这个 jquery 循环的执行时间?

rust - 如何将任意 Markdown 文件包含为文档属性?

rust - 如何在 Rust 的内置函数上实现特征?