루비(Ruby)의 차세대 가비지 컬렉터: MMTk 통합의 도전과 해결책

Reworking Memory Management in CRuby

작성자
발행일
2025년 09월 16일

핵심 요약

  • 1 호주국립대학교(ANU)와 Shopify는 Ruby에 고성능 가비지 컬렉터 프레임워크인 MMTk를 통합하여 차세대 GC를 개발 중입니다.
  • 2 MMTk 통합 과정에서 객체 이동(Copying GC) 및 병렬 파이널라이제이션 성능 저하 문제가 발생했으며, PPP(Potentially Pinning Parents) 개념 도입과 malloc 사용 회피로 해결했습니다.
  • 3 MMTk는 Ruby의 기본 GC보다 훨씬 정교한 다양한 GC 알고리즘을 제공하며, 이를 통해 Ruby의 메모리 관리 성능을 크게 향상시킬 잠재력을 가지고 있습니다.

도입

이 블로그 게시물은 2025년 국제 메모리 관리 심포지엄에서 발표된 논문을 기반으로, Ruby 프로그래밍 언어의 메모리 관리 개선을 위한 MMTk(Memory Management Toolkit) 통합 프로젝트에 대해 설명합니다. 호주국립대학교(ANU)와 Shopify의 협력을 통해 진행되는 이 프로젝트는 Ruby의 현재 가비지 컬렉터(GC)인 Mark and Sweep을 대체할 차세대 고성능 GC를 구축하는 것을 목표로 합니다. MMTk는 모듈화된 VM-중립 프레임워크로, NoGC, Mark and Sweep, Immix, Generational Immix, Sticky Immix 등 다양한 고급 GC 알고리즘을 제공하여 상당한 성능 향상을 기대할 수 있습니다. 현재 Ruby용 MMTk 구현은 두 가지 형태로 존재하며, 본 글에서는 MMTk 팀의 선행 구현을 중심으로 다룹니다.

MMTk를 Ruby에 통합하는 과정에서 객체 이동(Copying GC)과 병렬 파이널라이제이션 단계에서 주요 기술적 도전 과제에 직면했습니다.

1. 객체 이동(Copying Garbage Collector) 처리

  • 문제점: Ruby 2.7의 객체 이동 기능은 기존 데이터 타입의 객체 고정(pinning) 시스템과 MMTk 알고리즘의 마킹 및 이동 결합 방식이 충돌하여 비효율적인 힙 이중 스캔이 필요했습니다.
  • 해결책:
    • PPP(Potentially Pinning Parents) 개념 도입: 이동할 수 없는 참조를 포함할 가능성이 있는 객체를 PPP로 정의하고, 이들 객체를 최소화했습니다.
    • 최적화된 스캔: MMTk는 살아있는 PPP 객체 목록을 활용하여 GC 주기 초기에 빠르게 고정될 자식 객체를 식별한 후 마킹 및 이동 단계를 진행함으로써 효율성을 높였습니다.

2. 병렬 파이널라이제이션 성능 저하

  • 문제점: MMTk의 병렬 GC는 VM을 정지시키고 작동하는데, 초기에는 스레드 수가 증가할수록 파이널라이제이션 단계가 느려지는 현상이 발생했습니다. 이는 malloc으로 할당된 메모리를 해제하는 free 함수가 병렬 환경에서 스케일링되지 않아 병목 현상을 일으켰기 때문입니다.
  • 해결책:
    • malloc 사용 회피: Array, String, MatchData 같은 일반 타입의 버퍼를 malloc 대신 MMTk가 직접 관리하는 숨겨진 Ruby 객체로 할당했습니다.
    • 자동 메모리 관리: 이로써 버퍼 객체는 MMTk의 자동 메모리 관리를 받게 되었고, 파이널라이제이션 단계에서 별도의 free 작업이 필요 없어 성능 저하 문제를 해결했습니다.

결론

본 블로그 게시물에서는 Ruby에 MMTk를 통합하는 과정에서 마주했던 주요 도전 과제들, 즉 객체 이동을 위한 복사 가비지 컬렉터의 제약 사항과 병렬 파이널라이제이션 단계에서의 성능 저하 문제 및 그 해결책을 심도 있게 살펴보았습니다. PPP(Potentially Pinning Parents) 개념 도입과 `malloc` 사용을 회피하는 전략은 Ruby의 메모리 관리 효율성을 크게 개선하는 데 기여했습니다. 이러한 경험 공유는 Ruby 개발자, 가비지 컬렉터 연구자, 그리고 언어 설계자들에게 귀중한 통찰력을 제공할 것입니다. MMTk의 Ruby 포크에서는 최적화된 메모리 레이아웃, 새로운 객체 이동 기법, JIT 컴파일러와 GC의 통합 등 지속적인 연구 개발이 이루어지고 있으며, 이 과정에서 얻은 교훈은 Ruby 본류(upstream) 개선에도 활용될 예정입니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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