何时应在Rust中使用内联?

When should inline be used in Rust?

Rust具有" inline "属性,可以在以下三种口味之一中使用:

#[inline]

#[inline(always)]

#[inline(never)]

何时应使用它们?

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

The compiler automatically inlines functions based on internal heuristics. Incorrectly inlining functions can actually make the program slower, so it should be used with care.

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

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


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

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

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