YARV to LLVM의 소개 및 한계점
YARV to LLVM은 Ruby 1.9 VM(YARV)을 LLVM IR로 변환하고, LLVM의 최적화 기능과 네이티브 코드 변환을 활용합니다. Tom Bagby의 LLVM Ruby 라이브러리를 사용하며, 타입 추론 기능은 Ruby로 구현되어 성능 향상을 목표로 했습니다. 피보나치 계산에서 40배 가까운 속도 향상을 보여주었으며, SDL과 동적 컴파일된 헬로월드 프로그램 시연을 통해 가능성을 제시했습니다.
YARV to LLVM의 주요 문제점
-
성능 불균형: 일부 프로그램에서는 Ruby 1.9보다 느려지는 현상 발생. 이는 Ruby 1.9 런타임을 사용하면서, 네이티브 코드에서 박싱된 데이터를 기대하는 런타임 호출 시 불필요한 박싱/언박싱 오버헤드가 증가하기 때문입니다.
-
복잡한 타입 추론의 한계: 복잡한 코드(예: 중첩된 블록 호출)에서는 타입 추론이 불가능하여 최적화가 제한됩니다. 타입 추론 과정 자체가 여러 단계를 거치며 실행 시간이 증대되는 문제도 있었습니다.
-
유지보수 난이도: LLVM 코드 생성과 타입 추론 로직이 혼재된 프로그램 구조로 인해 버그 해결 및 유지보수가 매우 어려웠습니다.
-
기능 미지원:
eval,set_trace_func,BigNum과 같은 Ruby의 동적 기능들(일명 ‘블랙 매직’)은 타입 추론 결과를 무효화시킬 수 있어 구현이 불가능했습니다. 특히BigNum은 실행 중 메서드 및 스택 데이터 변경이 필요하며 빈번하게 사용되므로 성능 저하 없이 지원하기 어렵습니다.
YTL (YARV Translator)의 개발 및 해결 방안
YARV to LLVM의 한계를 극복하기 위해 YTL이 개발 중입니다. YTL은 풀셋 Ruby 지원을 목표로 하며, LLVM 대신 자체 네이티브 코드 생성 라이브러리인 YTL JIT를 구축합니다. 어셈블러는 Ruby로 작성되었으며, X86 32/64비트 네이티브 코드를 직접 생성합니다.
YTL의 문제 해결 전략
-
런타임 재구축 및 특수화: 런타임을 Ruby로 작성하여 타입 추론 결과에 따라 특정 타입에 최적화된(specialized) 코드를 생성합니다. 예를 들어, 정수만 다루는 정렬 함수는 정수형에 한정된 코드로 컴파일하여 박싱을 회피합니다. 컴파일 시간 증가는 타입 추론 결과를 마셜링(marshal)하여 재사용함으로써 해결합니다.
-
타입 추론 개선: 코드 생성과 타입 추론 로직을 분리하고, 타입 추론 처리 자체를 셀프 컴파일하여 네이티브 코드로 실행함으로써 복잡도와 추론 시간 문제를 해결합니다.
-
동적 컴파일 및 ‘블랙 매직’ 지원:
eval및BigNum과 같은 동적 기능은 동적 컴파일(On-Stack Replacement)을 통해 지원합니다. 이를 위해 실행 시 스택 프레임 및 객체를 새로운 타입 정보에 맞춰 재작성하는 기술을 활용하며, LLVM에서 어려웠던 스택 프레임 파악을 위해 어셈블러 레벨에서 코드 생성을 직접 제어합니다. 효율적인 동적 재컴파일을 위해 코드 스페이스 구조에도 특별한 설계를 적용하여 기본 블록 단위로 코드를 분할하고, 변경 발생 시 새로운 영역에 재할당하는 방식을 사용합니다.