Skip to content

Binary Size Reduction #30

@kioku

Description

@kioku

Current State

  • Release binary: 8.4MB
  • Debug binary: 26MB

Optimization Strategy

1. Compiler Optimizations (Quick Win - ~2-3MB reduction)

Add to Cargo.toml:

[profile.release]
strip = true          # Strip symbols
opt-level = "z"       # Optimize for size over speed
lto = "fat"          # Link-time optimization
codegen-units = 1    # Single codegen unit
panic = "abort"      # Smaller panic handler

2. Code-level Optimizations (~500KB-1MB)

Remove Unused Code:

  • Audit openapiv3 usage - might be pulling in unnecessary schemas
  • Check if all error variants are needed (40+ variants)
  • Remove debug/tracing code in release builds

String Optimization:

  • Use &'static str where possible instead of String
  • Consider string interning for repeated strings
  • Reduce string allocations in hot paths

Reduce Monomorphization:

  • Use dynamic dispatch (Box<dyn Error>) instead of generics where performance isn't critical
  • Combine generic functions that generate duplicate code

3. Alternative Build Strategies

Custom Build Profiles:

[profile.minimal]
inherits = "release"
opt-level = "z"
strip = true
lto = true
codegen-units = 1
panic = "abort"

[profile.size-optimized]
inherits = "release" 
opt-level = "s"      # Balance size/speed
strip = true
lto = "thin"         # Faster LTO
codegen-units = 1

Build commands:

# Smallest possible binary
cargo build --profile minimal

# Balanced size/performance
cargo build --profile size-optimized

Additional Cargo flags:

# Further size reduction
CARGO_PROFILE_RELEASE_OPT_LEVEL=z \
CARGO_PROFILE_RELEASE_LTO=fat \
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \
cargo build --release

# Use nightly for additional optimizations
cargo +nightly build -Z build-std=std,panic_abort \
  -Z build-std-features=panic_immediate_abort --release

Measurement Plan

Track binary size with:

# Check size
ls -lh target/release/aperture

# Analyze what's taking space (requires cargo-bloat)
cargo install cargo-bloat
cargo bloat --release --crates

# Check symbol sizes
nm -S target/release/aperture | sort -k2 -nr | head -20

Expected Results

  • Compiler optimizations alone: 8.4MB → 5.5-6MB
  • With code optimizations: 5-5.5MB
  • With nightly + build-std: Potentially <5MB

Trade-offs

  • opt-level = "z": ~10-20% slower execution
  • lto = "fat": Longer compile times (+30-60s)
  • panic = "abort": No stack unwinding on panic
  • Code optimizations: More complex code in some cases

Success Criteria

  • Binary < 6MB with standard release profile
  • Binary < 5.5MB with minimal profile
  • No functionality regression
  • Document size impact of different profiles

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions