【问题标题】:When should inline be used in Rust?什么时候应该在 Rust 中使用 inline?
【发布时间】:2016-06-05 06:58:18
【问题描述】:

Rust 有一个“内联”属性,可以用于这三种风格之一:

#[inline]

#[inline(always)]

#[inline(never)]

什么时候应该使用它们?

在 Rust 参考中,我们看到 an inline attributes section

编译器会根据内部启发式自动内联函数。错误的内联函数实际上会使程序变慢,因此应谨慎使用。

在 Rust 内部论坛中,huon 也是 conservative about specifying inline

但是我们在 Rust 源代码中看到了considerable usage,包括标准库。在单行函数中添加了很多内联属性,编译器应该很容易根据参考通过启发式发现和优化。这些实际上不需要吗?

【问题讨论】:

    标签: rust inline llvm-codegen


    【解决方案1】:

    当前 Rust 编译器的一个限制是,如果您不使用 LTO(链接时间优化),它永远不会跨 crate 内联未标记为 #[inline] 的函数。 Rust 使用类似于 C++ 的单独编译模型,因为 LLVM 的 LTO 实现不能很好地扩展到大型项目。因此,暴露给其他 crate 的小功能需要手工标记。这不是一个很好的情况,将来可能会通过对 LTO 和 MIR 内联的一些改进组合来解决。

    #[inline(never)] 有时对调试很有用(分离一段没有按预期工作的代码)。从理论上讲,它可以用于基准测试,但这通常是个坏主意:关闭内联并不会阻止其他过程间优化,例如常量传播。在普通代码方面,如果你有一个经常使用的仅用于错误处理的辅助函数,它可以减少代码大小。

    #[inline(always)] 通常是个坏主意;如果一个函数足够大以至于编译器默认不会内联它,那么它就足够大以至于调用的开销无关紧要(并且过多的内联会增加指令缓存压力)。有例外,但您需要性能测量来证明它的合理性。 This example 是一种值得考虑的情况。 #[inline(always)] 也可用于提高 -O0 代码质量,但这通常不值得担心。

    【讨论】:

    • 请注意,inline(never) 用于紧急内部函数,以确保优化器不会内联仅在紧急情况下调用的函数。
    • -1 因为第一点缺少一些东西。通用项可以跨 crate 内联,因为它们在实例化时会被有效地编译,因此内联所需的代码很容易获得。这意味着大量未标记的此类项目仍然可以内联交叉板条箱。在某些类型的基本库 crates 中,每个项目都是通用的!
    • 自编写以来,缺乏跨板条箱内联(缺少 LTO)的问题是否已修复?如果没有,并且有类似#[inline] pub fn f() { g() } 的东西,如果希望将g 内联到来自另一个板条箱的f 的调用者,是否也应该将g 注释为#[inline]
    猜你喜欢
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2011-04-15
    • 2017-04-10
    • 2012-03-19
    • 2018-05-12
    相关资源
    最近更新 更多