Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should inline be used in Rust?

Rust has an "inline" attribute that can be used in one of those three flavors:

#[inline]

#[inline(always)]

#[inline(never)]

When should they be used?

In the Rust reference, we see an inline attributes section saying

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.

In the Rust internals forum, huon was also conservative about specifying inline.

But we see considerable usage in the Rust source, including the standard library. A lot of inline attributes are added to one-line-functions, which should be easy for the compilers to spot and optimize through heuristics according to the reference. Are those in fact not needed?

like image 322
WiSaGaN Avatar asked Jun 05 '16 06:06

WiSaGaN


People also ask

When should inline be used?

One should use the inline function qualifier only when the function code is small. If the functions are larger you should prefer the normal functions since the saving in memory space is worth the comparatively small sacrifice in execution speed.

What does inline do in Rust?

The inline attribute suggests that the compiler should place a copy of the function or static in the caller, rather than generating code to call the function or access the static where it is defined. The compiler automatically inlines functions based on internal heuristics.

Why would you want to use inline?

An inline function is one for which the compiler copies the code from the function definition directly into the code of the calling function rather than creating a separate set of instructions in memory. This eliminates call-linkage overhead and can expose significant optimization opportunities.

Is inline necessary?

No, that does not matter at all. There are cases where it is appropriate to use inline in a .


1 Answers

One limitation of the current Rust compiler is that it if you're not using LTO (Link-Time Optimization), it will never inline a function not marked #[inline] across crates. Rust uses a separate compilation model similar to C++ because LLVM's LTO implementation doesn't scale well to large projects. Therefore, small functions exposed to other crates need to be marked by hand. This isn't a great situation, and it's likely to be fixed in the future by some combination of improvements to LTO and MIR inlining.

#[inline(never)] is sometimes useful for debugging (separating a piece of code which isn't working as expected). In theory, it can be used for benchmarking, but that's usually a bad idea: turning off inlining doesn't prevent other inter-procedural optimizations like constant propagation. In terms of normal code, it can reduce codesize if you have a frequently used helper function which is only used for error handling.

#[inline(always)] is generally bad idea; if a function is big enough that the compiler won't inline it by default, it's big enough that the overhead of the call doesn't matter (and excessive inlining increases instruction cache pressure). There are exceptions, but you need performance measurements to justify it. This example is the sort of situation where it's worth considering. #[inline(always)] can also be used to improve -O0 code quality, but that's not usually worth worrying about.

like image 112
Eli Friedman Avatar answered Sep 29 '22 22:09

Eli Friedman