Description
Rust's linkage model means that crates compile to one object file. Linkers today will pull in an entire object file if any symbol from it is used during linkage. This means that if you link to the standard library that you're pulling in the entire library no matter what. This can be circumvented with LTO, but that requires a lot of work on LLVM's part and takes a significant amount of time.
I believe that we can get similar gains through --gc-sections
(-dead_strip
on osx). All of our object code is emitted to the same section, so this flag currently doesn't eliminate much code. Issue #12140 proposed turning -ffunction-sections
on by default, but this causes object size bloat as well as slowing down link times for small crates.
I believe that we may be able to strike a compromise by placing each module's functions in their own section. This reduces the number of sections from thousands to dozens, with the sections being much larger. In this manner, in theory if you don't use any functions from the std::f64
module the entire module can be omitted from linkage.
I would like to investigate the impact of turning these features on by default for all rust compilations. Concretely, this involves two steps:
- Instruct LLVM to place each function in a section corresponding to the enclosing module's name.
- Pass
-Wl,--gc-sections
to the linker by default (-Wl,-dead_strip
on osx). Also add-C no-gc-sections
to turn off passing this flag.
Note that I think we need to be careful to ensure that the linker doesn't GC away metadata for dylibs, but other than that I believe rust code can safely run with --gc-sections
for now.