Course contentsShow
← Rust
Lesson 748 of 1,9106. Generics and Static DispatchFree lesson

Binary Size Optimization Techniques

Apply linker-level optimizations for generic code to remove unused template instantiations.

In this lesson, you will learn how to leverage linker-level optimizations to prune unused generic template instantiations and shrink your final binary size.

When you write a generic function in Rust, the compiler performs "monomorphization." This means it generates a unique, concrete version of that function for every type you use with it. If your code uses process<T> with 50 different types, the compiler produces 50 distinct machine code functions. While this is great for performance, it leads to "code bloat" if many of those versions are functionally identical or effectively unused in the final execution path.

The Linker’s Role: Dead Code Elimination

The linker is responsible for stitching these object files together into an executable. By default, the linker is cautious—it wants to make sure that if you might need a function, it stays in the binary. However, we can instruct the compiler and linker to be more aggressive in removing unused instantiations.

To prune these, we use Function Sections. By placing every function into its own unique section of the object file, the linker can perform Dead Code Elimination (DCE): if a specific generic instantiation isn't referenced by your main entry point, the linker can simply discard the entire section.

You can enable this in your Cargo.toml:

[profile.release]
# Place each function in its own section
codegen-units = 1
# Allow the linker to discard unused sections
lto = "fat" 

Why This Matters

  • codegen-units = 1: This tells the compiler to optimize the entire crate as one unit. While this increases compilation time, it gives the compiler a global view to identify which generic instantiations are actually redundant.
  • lto = "fat": Link Time Optimization allows the compiler to look across crate boundaries at the final stage. It recognizes that if MyGeneric<u32> and MyGeneric<i32> are never called, or if their logic can be collapsed, they can be stripped away entirely.

By forcing the compiler to consolidate and the linker to prune, you prevent your binary from becoming a graveyard of unused, type-specific function copies.

Key Takeaway: Use codegen-units = 1 and lto = "fat" to enable the linker to identify and discard unused generic instantiations, significantly reducing binary bloat.