Ruby Ractor 로컬 가비지 컬렉션 최적화

[EN] Toward Ractor local GC / Koichi Sasada @ko1

작성자
RubyKaigi
발행일
2025년 05월 27일

핵심 요약

  • 1 Ruby Ractor의 병렬 컴퓨팅 성능 향상을 위해 Ractor별 독립적인 로컬 가비지 컬렉션(GC) 도입이 제안되었습니다.
  • 2 핵심 과제는 Ractor 간 공유되는 '공유 가능 객체'의 참조를 안전하게 관리하는 것이며, 기존 방식은 전체 Ractor 정지로 병렬성을 저해합니다.
  • 3 제안된 보수적인 접근 방식은 공유 가능 객체를 항상 살아있는 것으로 간주하고 로컬 GC를 병렬로 실행하며, 마이크로벤치마크에서 상당한 성능 향상을 보였습니다.

도입

Ruby 3.0에 도입된 Ractor는 병렬 컴퓨팅과 견고한 동시성 프로그래밍을 위한 새로운 모델입니다. 각 Ractor는 독립적인 객체 공간을 제공하여 스레드 안전성을 높이고 공유 가능한 변경 가능한 상태로 인한 버그를 방지합니다. 그러나 현재의 전역 가비지 컬렉션(GC) 방식은 모든 Ractor를 일시 중지시켜 병렬 실행의 이점을 상쇄시키는 한계를 가집니다. 이러한 배경에서 각 Ractor가 독립적으로 GC를 수행하는 'Ractor 로컬 GC'의 도입 필요성이 제기되었습니다.

Ractor 로컬 GC의 핵심 난관은 여러 Ractor에서 참조될 수 있는 ‘공유 가능 객체’ 처리입니다. 로컬 GC 시 공유 가능 객체가 참조 없다고 오인되어 해제되면 심각한 버그를 유발합니다. Ractor 간 참조를 실시간으로 정확히 추적하는 것은 병렬 환경에서 매우 복잡하며 성능 오버헤드를 초래합니다. 현재 Ruby는 전역 객체 공간을 사용하며, GC 시 모든 Ractor를 중지해야 하므로 느리고 병렬성을 활용할 수 없습니다.

이를 해결하기 위해 발표자는 보수적인 접근 방식을 제안합니다: 로컬 GC 동안 공유 가능 객체를 ‘항상 살아있는’ 것으로 가정하고 GC 루트로 처리합니다. 이 방식은 대부분의 공유 가능 객체가 수명이 길고 수가 적다는 점을 활용합니다. 안전한 병렬 로컬 GC를 가능하게 하며, 더 이상 참조되지 않는 객체는 필요시 비주기적인 전역 GC를 통해 회수됩니다. 이로 인한 일부 메모리 잔류는 병렬 실행으로 인한 전반적인 성능 향상으로 상쇄됩니다.

마이크로벤치마크 평가 결과, 이 접근 방식은 상당한 성능 개선을 입증했습니다. 짧은 수명 객체 생성 테스트에서 로컬 GC 버전은 16개 Ractor에서 약 5배 속도 향상을, 긴 수명 객체 테스트에서는 4배 이상 향상을 보였습니다. 정규 표현식 매칭에서도 유사한 개선이 관찰되었습니다. 이는 ‘완벽한 것보다 실행하는 것이 낫다’는 통찰을 보여주며, 보수적인 구현만으로도 실질적인 성능 향상이 가능함을 시사합니다.

결론

결론적으로, Ruby Ractor를 위한 로컬 가비지 컬렉션 도입은 Ruby의 동시성 및 전반적인 성능을 크게 향상시킬 유망한 방향입니다. 공유 가능 객체 관리의 복잡성에도 불구하고, 모든 공유 가능 객체를 살아있는 것으로 간주하는 보수적인 접근 방식은 안전하고 실용적인 해결책을 제공하며, 마이크로벤치마크에서 그 효과가 입증되었습니다. 향후 Ruby 3.5에 이 기능을 구현하고, 전역 GC의 병렬 마킹을 추가하며, 궁극적으로 더욱 정교한 공유 객체 참조 추적 방식을 모색하는 것이 목표입니다. 이 연구는 Ruby의 병렬 처리 능력을 한 단계 발전시키는 중요한 협력 결과입니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!