What is LTO?
LTO means Link-Time Optimization. It is generally set up to use the regular optimization passes used to produce object files... at link time instead, or in addition.
Why does it matter?
A compiler does not inherently optimize for speed over size or size over speed; and therefore neither does LTO.
Instead, when invoking the compiler, the user selects a profile. For rustc
:
O0
, O1
, O2
and O3
are optimizing for speed.
Os
and Oz
are optimizing for size.
LTO can be combined on top of any optimization level, and will follow the selected profile.
So why did the size increase?
By default, the [release]
profile instructs cargo
to invoke rustc
with O2
or O3
, which attempts to optimize for speed over size.
In particular, O3
can rely quite heavily on inlining. Inlining is all about giving more context to the optimizer, and therefore more optimization opportunities... LTO offers more chances to apply inlining (more known functions), and here it appears that more inlining happened.
So why did this blog post claim it reduced size?
It also reduces size. Possibly.
By giving more context, the optimizer/linker can realize that some portion of the code or dependencies are not used at all, and therefore can be elided.
If using Os
or Oz
, the size is near certain to go down.
If using O2
or O3
, unused code is removed while inlining adds more code, so it's quite unpredictable whether the end result is bigger or smaller.
So, LTO?
LTO gives the optimizer a better opportunity at optimizing, so it's a good default for Releases.
Just remember that cargo
leans toward speed over size by default, and if this does not suit you, you may want to select another optimization direction.