[Rust] 러스트 바이너리 파일 크기 줄이기

Summary

1. --release 옵션을 주어 릴리즈 모드로 컴파일

2. 배포전에 LTO 활성화 및 바이너리 strip 옵션

3. 메모리 집약적 프로그램이 아닐 경우 system allocator 사용

4. 훨씬 큰 프로그램을 사용할 경우 UPX / 압축 사용

5. 그외 더 작게 만드는 방법은 여러가지 방법을 사용

 

 

Optimization Level Table

0 no optimizations
1 basic optimizations
2 some optimizations
3 all optimizations
"s" optimize for binary size
"z" optimize for binary size, but also turn off loop vectorization.

https://doc.rust-lang.org/cargo/reference/profiles.html#opt-level

 


Release로 빌드 (opt-level : 3)

Release로 빌드하는 방법은 단순히 옵션 값 하나만 주면 된다.

$ cargo build --release

 

debug 모드에서는 최적화를 비활성화한다. 그리고 디버거를 제공하고 IDE가 실행하기 때문에 파일 크기가 크다.

[profile.dev]
opt-level = 0

[profile.release]
opt-level = 3

release 모드에서는 모든 최적화를 거치게 된다.

모드 Optimization 컴파일 속도 실행 성능 파일 크기
debug opt-level = 0 상대적으로 빠름 상대적으로 느림 상대적으로 큼
release opt-level = 3 상대적으로 느림 상대적으로 빠름 상대적으로 작음

 

Size 최적화 (opt-level : "z")

이전에 언급한 Optimization level 3은 release 모드의 기본값이지만, 파일 크기를 줄이는 목적이 아닌 실행 성능을 위한 최적화에 가깝다.

최소한의 크기를 갖기 위해선 Optimization level을 z로 설정한다.

 

[profile.release]
opt-level = "z" # Optimize for size

 

어떤 상황에서는 opt-level이 s일 때 더 작을 수 있다.

 

 

LTO : Link Time Optimization 활성화

[profile.release]
lto = true

LTO는 링커를 최적화하는 기법입니다. 사용하지 않는 라이브러리, Dead code 등을 정리해 크기를 줄인다.

하지만 LTO는 컴파일러의 포인팅(함수 호출)까지는 최적화할 수 없다.

 

 

Jemalloc 제거 (Rust 1.32 이전 버전일 경우)

use std::alloc::System;

#[global_allocator]
static A: System = System;

Rust가 구버전일 경우 Jemalloc이 기본적으로 사용되는데 이걸 제거하여 크기를 줄일 수 있다.

 

바이너리 압축

$ upx --best --lzma target/release/{binary}

 

 


레퍼런스

 

1. Hackers News : Why is a Rust executable large?

https://news.ycombinator.com/item?id=11823949

https://lifthrasiir.github.io/rustlog/why-is-a-rust-executable-large.html

 

2. Github : min-sized-rust (개인적으로 제일 깔끔하고 추천)

https://github.com/johnthagen/min-sized-rust 

 

3. Github : 설정별 크기 예시 표

https://github.com/rust-lang/rust/pull/55011#issuecomment-429336055

 

4. Rust Documents

https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles

 

 

 


무서운 사진