什么时候应该在 Rust 中使用内联?
When should inline be used in Rust?
Rust 有一个 "inline" 属性,可用于这三种风格之一:
#[inline]
#[inline(always)]
#[inline(never)]
什么时候使用它们?
在 Rust 参考中,我们看到 an inline attributes section 说
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 也是 conservative about specifying inline。
但我们在 Rust 源代码中看到 considerable usage,包括标准库。单行函数中添加了很多内联属性,编译器应该很容易根据参考资料通过启发式方法发现和优化。那些实际上不需要吗?
当前 Rust 编译器的一个限制是,如果您不使用 LTO(Link-时间优化),它永远不会跨板条箱内联未标记 #[inline]
的函数。 Rust 使用类似于 C++ 的单独编译模型,因为 LLVM 的 LTO 实现不能很好地扩展到大型项目。因此,暴露给其他 crate 的小函数需要手工标记。这不是一个很好的情况,将来可能会通过对 LTO 和 MIR 内联的一些改进组合来解决。
#[inline(never)]
有时对调试很有用(分离一段没有按预期工作的代码)。从理论上讲,它可以用于基准测试,但这通常是个坏主意:关闭内联不会阻止其他过程间优化,如常量传播。就普通代码而言,如果你有一个经常使用的辅助函数,它只用于错误处理,它可以减少代码大小。
#[inline(always)]
通常是个坏主意;如果一个函数足够大以至于编译器默认不会内联它,那么它就足够大以至于调用的开销无关紧要(过多的内联会增加指令缓存压力)。有例外,但您需要性能测量来证明它的合理性。 This example 是一种值得考虑的情况。 #[inline(always)]
也可用于提高 -O0
代码质量,但这通常不值得担心。
Rust 有一个 "inline" 属性,可用于这三种风格之一:
#[inline]
#[inline(always)]
#[inline(never)]
什么时候使用它们?
在 Rust 参考中,我们看到 an inline attributes section 说
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 也是 conservative about specifying inline。
但我们在 Rust 源代码中看到 considerable usage,包括标准库。单行函数中添加了很多内联属性,编译器应该很容易根据参考资料通过启发式方法发现和优化。那些实际上不需要吗?
当前 Rust 编译器的一个限制是,如果您不使用 LTO(Link-时间优化),它永远不会跨板条箱内联未标记 #[inline]
的函数。 Rust 使用类似于 C++ 的单独编译模型,因为 LLVM 的 LTO 实现不能很好地扩展到大型项目。因此,暴露给其他 crate 的小函数需要手工标记。这不是一个很好的情况,将来可能会通过对 LTO 和 MIR 内联的一些改进组合来解决。
#[inline(never)]
有时对调试很有用(分离一段没有按预期工作的代码)。从理论上讲,它可以用于基准测试,但这通常是个坏主意:关闭内联不会阻止其他过程间优化,如常量传播。就普通代码而言,如果你有一个经常使用的辅助函数,它只用于错误处理,它可以减少代码大小。
#[inline(always)]
通常是个坏主意;如果一个函数足够大以至于编译器默认不会内联它,那么它就足够大以至于调用的开销无关紧要(过多的内联会增加指令缓存压力)。有例外,但您需要性能测量来证明它的合理性。 This example 是一种值得考虑的情况。 #[inline(always)]
也可用于提高 -O0
代码质量,但这通常不值得担心。