【问题标题】:Is it better to return by value for small types for getters in traits?对于特征中的 getter 来说,按值返回是否更好?
【发布时间】:2020-12-07 04:30:47
【问题描述】:

对于大多数数据类型,我遵循 https://stackoverflow.com/a/35391084/11963778 中的约定并让 getter 返回引用:

trait HasName {
    fn name(&self) -> &String;
    fn name_mut(&mut self) -> &mut String;
}

但是,对于具有复制语义并且小于(或大约)指针大小的数据类型,我是否应该使用 getter 方法来返回值?它看起来像这样:

trait HasNum {
    fn num_v(&self) -> i32;
    fn num(&self) -> &i32;
    fn num_mut(&mut self) -> &mut i32;
}

使用返回值的 getter 是一种好习惯吗?如果是这样,那么对于小数据类型,我应该执行多大的操作?

【问题讨论】:

标签: rust reference return-value traits getter


【解决方案1】:

根据经验,您可以复制保存在单个缓存行上的值,而不是使用引用。虽然 x86 上的缓存行通常为 64 字节,但英特尔建议将数据限制为 16 字节,以减少值不对齐的机会。

因此,换句话说,只需复制大小约为[i32; 4] 或更小的任何内容都可以。

注意:虽然背后有一些原因,但我只是根据我目前对性能的了解制定了这条规则。如果有足够多的人看这篇文章,我相信其他人会有更好的答案。话虽如此,即使我的推理有点偏离,我认为在大多数情况下,当您不尝试优化极其时间关键的代码片段或特定 CPU 时,它仍然可能成立。 p>

在我写这个答案的过程中,我还在this question 中发现了一些更有趣的点。

  • https://stackoverflow.com/a/40185996/5987669

    例如,对于具有导致“最佳位置”的架构(机器寄存器、内存架构等)的机器来说,这是很常见的——复制某种大小的变量是最“有效的”,但复制更大的 OR较小的变量则更少。较大的变量将花费更多的复制成本,因为可能需要对较小的块进行多次复制。较小的也可能成本更高,因为编译器需要将较小的值复制到较大的变量(或寄存器)中,对其进行操作,然后将值复制回来。

  • https://stackoverflow.com/a/49523201/5987669
    这个答案是针对 C 的,但如果它也适用于 Rust,我不会感到惊讶

    有一种称为 IPA SRA 的 GCC 优化,它自动将“按引用传递”替换为“按值传递”:https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html (-fipa-sra)
    ...
    因此,启用此优化后,使用小类型的引用应该与按值传递它们一样快。

    另一方面,按值传递(例如)std::string 无法优化到按引用速度,因为涉及到自定义复制语义。

【讨论】:

    猜你喜欢
    • 2010-09-26
    • 1970-01-01
    • 2014-07-27
    • 2018-01-02
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    • 2010-10-17
    • 2023-03-02
    相关资源
    最近更新 更多