Trawling

Nicholas Nethercote, Rust 증분 빌드 Span의 테이블 저장 비율 20~40%에서 약 1%로 낮춰

Nicholas Nethercote는 Hexcat을 위한 Rust 컴파일러 성능 작업에서 Span 압축을 바꿔 증분 빌드의 전역 테이블 저장 비율을 통상 20~40%에서 약 1%로 낮췄다고 보고했습니다. 2026년 9월 28일~11월 2일 여러 최적화가 반영된 벤치마크 집계에서는 변동 기준 아래 결과까지 포함한 평균 wall-time이 2.85% 감소했습니다.

본문

Nicholas Nethercote는 Hexcat을 위한 Rust 컴파일러 성능 작업 첫 달을 2026년 11월 4일 개인 블로그에 정리했습니다. 그가 소개한 변경 가운데 하나는 Span의 압축 방식 교체입니다. 이로써 증분 빌드에서 전역 테이블에 저장되는 Span의 비율이 기존 통상 20~40%에서 약 1%로 줄었다고 보고했습니다.

Span은 Rust 컴파일러의 AST·HIR·MIR 노드마다 붙어 코드 위치 등을 추적합니다. 크레이트의 소스 파일을 이어 붙인 버퍼에서 lo와 hi가 위치를 가리키고, context는 매크로 등에 필요한 위생·출처 문맥을 담습니다. parent는 소스 위치가 조금 바뀔 때 컴파일 시간에 미치는 영향을 줄이기 위한 상대 위치 정보입니다. 네 필드는 각각 32비트여서 원래 16바이트지만, 흔한 경우에는 세 가지 8바이트 인라인 형식 가운데 하나로 압축합니다. 나머지는 전역 테이블에 저장합니다. 위치 사이 길이가 짧거나 context·parent가 0인 경우가 많고, 값이 있는 경우에도 대체로 작다는 점을 압축에 활용합니다. parent는 증분 빌드에서만 사용됩니다.

기존 표현은 context와 parent가 함께 있는 Span을 인라인으로 담지 못해 항상 테이블에 저장했습니다. Rust PR #163857은 이 조합의 대부분을 담는 새 InlinePair 형식을 도입했습니다. lo와 길이에 할당하는 비트 폭을 줄여 두 정보를 함께 담습니다. parent만 담는 새 형식도 기존보다 길이와 parent 필드를 각각 1비트씩 줄입니다. 네더코트는 context를 인터닝하는 경우에도 인라인에 유지하도록 했다고 설명했습니다. context만 따로 읽는 일이 잦기 때문입니다.

네더코트에 따르면 압축 방식 교체는 여러 벤치마크에서 명령어 수를 줄였고, 가장 큰 감소 폭은 3%를 넘었습니다. 사이클 수 감소 폭은 더 컸으며, 인터닝이 줄어든 만큼 증분 빌드에서 개선이 가장 크게 나타났다고 밝혔습니다.

별도의 최적화에서는 메타데이터 인코딩·디코딩과 안정 해시 계산 중 같은 parent Span의 정보를 해시 테이블에서 반복해 찾는 경로에 단일 항목 캐시를 추가했습니다. 직전과 같은 parent 정보가 필요하면 캐시에 둔 값을 사용해 테이블 조회를 건너뜁니다. 이 변경도 여러 벤치마크의 명령어 수를 줄였으며, 가장 큰 감소 폭은 4%를 넘었습니다. 네더코트는 이 개선이 주로 증분 컴파일에서 나타났다고 보고했습니다. 압축 변경은 테이블에 저장하는 Span을 줄이고, 캐시는 parent 정보의 반복 조회를 줄입니다.

기간 전체의 wall-time 집계는 2026년 9월 28일부터 11월 2일까지 여러 최적화가 반영된 벤치마크 결과입니다. 변동 기준을 넘긴 결과에서는 45개 벤치마크의 236개 테스트가 개선됐고, 3개 벤치마크의 4개 테스트가 회귀했습니다. 변동 기준에 못 미친 결과까지 포함하면 개선 599건, 회귀 90건으로 집계됩니다. 네더코트가 제시한 평균 wall-time 2.85% 감소는 이 확장 집계에 해당합니다.

자료: Nicholas Nethercote 개인 블로그 / 정리·해설: Trawling

참고 자료

오류 제보