何时应该在Rust中使用内联?

WiS*_*GaN 54 inline rust llvm-codegen

Rust有一个"内联"属性,可以用于以下三种风格之一:

#[inline]

#[inline(always)]

#[inline(never)]

什么时候应该使用它们?

在锈参考,我们看到了一个内嵌属性部分说法

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

在Rust内部论坛中,huon 对于指定内联也很保守.

但是我们在Rust源代码中看到了相当多的用法,包括标准库.许多内联属性被添加到单行函数中,编译器应该可以根据参考通过启发式查找和优化.那些实际上不需要吗?

Eli*_*man 47

当前Rust编译器的一个限制是,如果您不使用LTO(链接时优化),它将永远不会内联未#[inline]在包装箱中标记的功能.Rust使用类似于C++的单独编译模型,因为LLVM的LTO实现不能很好地扩展到大型项目.因此,暴露在其他板条箱中的小功能需要手工标记.这不是一个很好的情况,并且通过LTO和MIR内联的一些改进可能会在未来得到修复.

#[inline(never)]有时用于调试(分离一段未按预期工作的代码).从理论上讲,它可以用于基准测试,但这通常是一个坏主意:关闭内联并不会阻止其他程序间优化,如不断传播.就普通代码而言,如果你有一个经常使用的辅助函数,它只能用于错误处理,它可以减少代码.

#[inline(always)]通常是坏主意; 如果函数足够大以至于编译器默认不会内联它,那么它的大小足以使调用的开销无关紧要(并且过多的内联会增加指令缓存压力).也有例外,但您需要进行性能测量才能证明这一点. https://github.com/rust-lang/rust/commit/274bb24efdbeed0ab1a91f3c02f86551ef16eac7是值得考虑的情况. #[inline(always)]也可用于提高-O0代码质量,但这通常不值得担心.

  • 请注意,在恐慌内在函数上使用`inline(never)`来确保优化器不会内联仅在恐慌情况下调用的函数. (13认同)
  • -1,因为第一点还缺少一些东西。泛型项目可以跨板条箱内联,因为它们在实例化时可以有效地进行编译,因此内联所需的代码很容易获得。这就意味着大量未标记的此类项目仍可以跨箱内联。在某些基本的库箱中,每个项目都是通用的! (2认同)
  • 自编写以来,缺少跨板条箱内联(缺少 LTO)的问题是否已经修复?如果没有,并且有诸如“#[inline] pub fn f() { g() }”之类的内容,如果希望将“g”内联到“f”中,则“g”也应该注释为“#[inline]” ` 来自另一个板条箱的呼叫者? (2认同)