# Aleksey Kladov - Inline in Rust (Highlights) ![rw-book-cover|256](https://readwise-assets.s3.amazonaws.com/static/images/article1.be68295a7e40.png) ## Metadata **Cover**:: https://readwise-assets.s3.amazonaws.com/static/images/article1.be68295a7e40.png **Source**:: #from/readwise **Zettel**:: #zettel/fleeting **Status**:: #x **Authors**:: [[Aleksey Kladov]] **Full Title**:: Inline in Rust **Category**:: #articles #readwise/articles **Category Icon**:: 📰 **URL**:: [matklad.github.io](https://matklad.github.io//2021/07/09/inline-in-rust.html) **Host**:: [[matklad.github.io]] **Highlighted**:: [[2021-07-25]] **Created**:: [[2022-09-26]] ## Highlights - It gives the compiler the necessary context to apply further transformations. - To achieve separate compilation, compilers expose signatures of functions, but keep function bodies invisible to other modules, preventing inlining. - In Rust, a unit of (separate) compilation is a crate. - it enables cross-crate inlining. #c1 - the compiler implements this by compiling a separate copy of the #[inline] function with every crate it is used in, significantly increasing compile times. #c2 - Besides #[inline], there are two more exceptions to this. Generic functions are implicitly inlinable. #c1 - The other exception is link-time optimization. LTO opts out of separate compilation #c2 ### Inlining in Practice - First, it’s not a good idea to apply #[inline] indiscriminately, as that makes compile time worse. If you don’t care about compile times, a much better solution is to set lto = true in Cargo profile https://doc.rust-lang.org/cargo/reference/profiles.html#lto - Second, it usually isn’t necessary to apply #[inline] to private functions — within a crate, the compiler generally makes good inline decisions. - Third, when building an application, apply #[inline] reactively when profiling shows that a particular small function is a bottleneck. - Fourth, when building libraries, proactively add #[inline] to small non-generic functions. Pay special attention to impls: Deref, AsRef and the like often benefit from inlining. A library can’t anticipate all usages upfront, it makes sense to not prematurely pessimize future users. - Fifth, mind generic functions. It’s not too wrong to say that generic functions are implicitly inline. As a result, they often are a cause for code bloat. - Separate-compilation friendly private implementation. #rust #example #code code block ``` // Public, generic function. // Will cause code bloat if not handled carefully! pub fn parse_str(wat: impl AsRef<str>) -> Result<Vec<u8>> { // Immediately delegate to a non-generic function. _parse_str(wat.as_ref()) } // Separate-compilation friendly private implementation. fn _parse_str(wat: &str) -> Result<Vec<u8>> { ... } ```