Rust's derive often implies inline
Rust의 derive는 종종 inline을 암시합니다
Rust에서 `#[derive(Debug)]`를 쓰면 생성된 구현에 `#[inline]`이 붙는 경우가 많습니다. 간단한 구현에서는 성능에 도움이 되지만, 큰 오류 타입의 `Debug` 구현을 반복해서 인라인하면 바이너리 크기가 커질 수 있습니다. 글쓴이는 uv 바이너리에서 특정 구현의 인라인을 막아 약 160KB를 줄였습니다.
- 주제
AI 요약
Rust에서는 Debug, Display, Clone 같은 트레이트를 #[derive(...)]로 구현하는 일이 흔합니다. 글쓴이는 derive가 생성하는 코드에 #[inline]도 붙는다는 사실을 최근에 알았습니다. 명세가 이를 보장하지는 않지만, Rust Reference의 예제에서 암시하며 매크로 확장 결과에서도 확인할 수 있습니다.
인라인이 바이너리 크기를 키우는 경우
#[inline]은 컴파일러에 주는 힌트입니다. derive로 생성하는 Debug나 Clone 구현은 대개 간단해 인라인하면 이득을 봅니다. 하지만 많은 변형과 필드를 가진 오류 계층에서는 Debug 구현이 상당한 코드로 커질 수 있습니다. 이 구현을 호출할 때마다 코드가 인라인되면 디버그나 트레이스 로그를 반복해서 남기는 경로에서 바이너리 크기가 늘어납니다. 글쓴이와 동료들은 특정 Debug 구현의 인라인을 막아 uv 바이너리 크기를 약 160KB 줄였습니다. 글쓴이는 크기 비용이 빠르게 쌓였고, rustc가 인라인 코드 크기나 횟수에 제한을 두지 않는 듯한 점이 놀라웠다고 말합니다. 다만 많은 프로그램에서는 현재 동작이 적절할 수 있다고 덧붙입니다.
Lobsters 반응
- @kornel —
Ord와Eq, 어쩌면Clone에#[inline]을 붙이는 건 예상하겠지만,Debug에 붙는 건 놀랍습니다. 저는fmt구현에#[cold]를 붙입니다! - @aw1621107 — 참고로
Debug에#[inline]을 추가한 2023년 PR은 일반적으로 벤치마크 수치가 더 좋아졌기 때문입니다. 흥미롭게도 필드가 5개 이하인 구조체에만 이 속성을 붙이는 실험용 PR은 항상 속성을 붙이는 방식보다 성능이 나빠졌습니다. - @tsion —
#[inline]은 힌트일 뿐이라는 말은 정확하지 않습니다. 다른 크레이트에서 인라인할 수 있게 해주는 역할도 합니다. 제네릭은 원래 크레이트 경계를 넘어 인라인할 수 있지만, 제네릭이 아닌 함수는 기본적으로 불가능합니다. 힌트 없이 크레이트 간 인라인만 허용하는#[can_inline]이 있으면 좋겠습니다. - @jtdowney — 흥미로운 글입니다. 참고로 마지막 문단의 ‘limit’라는 단어에 오타가 있습니다.
원문: Yossarian / 번역·요약: Trawling