何时应在Rust中使用内联?


85

Rust具有“内联”属性,可用于以下三种口味之一:

#[inline]

#[inline(always)]

#[inline(never)]

什么时候应该使用它们?

在Rust参考中,我们看到一个内联属性部分

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

在Rust内部知识论坛中,huon在指定inline方面也很保守

但是我们在Rust源中看到了很多用法,包括标准库。许多内联属性被添加到单行函数中,对于编译器来说,根据参考文献,通过启发式方法可以很容易地发现并优化它们。实际上不需要那些吗?

Answers:


69

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

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

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


19
请注意,该inline(never)函数用于紧急情况内在函数,以确保优化程序不会内联仅在紧急情况下调用的函数。
oli_obk 2016年

4
-1,因为第一点还缺少一些东西。泛型项目可以跨包装箱内联,因为它们在实例化时可以有效地编译,因此内联所需的代码很容易获得。这意味着大量未标记的此类项目仍可以跨箱内联。在某些基本的库箱中,每个项目都是通用的!
bluss
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.