TL;DR
- Rust의
#[derive(...)]는 현재 파생 구현에#[inline]을 붙이는 경우가 많으며, 단순 구현에는 유리하지만 중첩된 오류 유형에서는 바이너리 크기를 늘릴 수 있음. Debug,Display,Clone같은 핵심 트레이트는#[derive(...)]로 구현하는 방식이 흔함.#[inline]은 보장된 동작은 아니지만, Rust 레퍼런스의 예시와 매크로 확장 결과에서 파생 구현에 포함되는 것을 확인할 수 있음.- 중첩된 오류 계층의
Debug구현은 호출 때마다 인라인될 수 있는 코드가 많으며, 디버그 또는 추적 로그에서 반복 호출될 수 있음. #[inline(never)]를 적용하는 자체 프로시저 매크로를 사용해uv바이너리 크기를 약 160KB 줄였으며, 이는 모든 프로그램에서 인라인 제한이 바람직하다는 뜻은 아님.
핵심 트레이트 파생과 inline
- Rust에서
Debug,Display,Clone같은 핵심 트레이트를 구현하는 가장 흔한 방법 중 하나는#[derive(...)]를 사용하는 것임. - 간단한 구조체에
#[derive(Debug)]를 적용하고 매크로를 확장하면, 생성된Debug::fmt구현에#[inline]이 포함됨. #[inline]포함은 보장된 동작으로 보이지 않지만, 레퍼런스의 예시에서 암시되며 매크로 확장 결과에서도 확인 가능함.#[inline]은 힌트일 뿐이며, 일반적으로 단순한Debug,Clone등의 파생 구현은 인라인의 이점을 얻음.
중첩된 오류 유형에서 커지는 코드
- 예시의 오류 계층은 여러
String필드를 가진ErrorA,ErrorA를 포함하는ErrorB,ErrorB를 포함하는ErrorC, 그리고 세 유형을 변형으로 갖는Errors열거형으로 구성됨. - 생성된
Debug구현은 구조체 필드와 열거형 변형을 각각 처리하며, 각 구현 함수에#[inline]이 붙음. Errors의Debug구현을 호출할 때마다 이 계층의 상당한 코드가 인라인될 수 있으며, 디버그 또는 추적 로그에서 반복 호출되는 경우가 있음.- 실제 Rust 애플리케이션의 오류 열거형 계층은 예시보다 훨씬 깊고 필드 수도 적지 않은 경우가 많음. 제시된 계층은 크게 단순화된 예시임.
바이너리 크기 영향
- 파생된
Debug구현을 인라인하지 않도록 하자 바이너리 크기를 약 160KB 줄일 수 있었음. - 이를 위해
derive(Debug)처럼 동작하지만#[inline(never)]를 적용하는 자체 프로시저 매크로를 추가함. - 코드 크기 비용은 빠르게 누적될 수 있으며,
rustc가Debug구현의 크기나 인라인 횟수에 제한을 두지 않는 듯하다는 점도 놀라움의 원인임. - 다만 많은 프로그램에서는 현재의 인라인 결정이 적절할 것으로 보임.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요