Class#new는 Ruby 객체 생성의 핵심 메서드로, 현재 C 언어로 구현되어 있습니다. 발표자는 C 구현을 Ruby로 전환하고 인라인화를 통해 성능을 최적화하는 방안을 제시합니다.
성능 저하 요인 및 최적화 기회
- 언어 간 호출 규약 전환: Ruby와 C 간 Class#new 호출 시 발생하는 호출 규약 전환 비용이 성능 저하 요인입니다.
- 인라인 캐시: 메서드 탐색 가속화에 필수적인 인라인 캐시는 C 함수에서 Ruby 메서드 호출 시 효율이 낮아 캐시 미스는 속도를 최대 40% 저하시킵니다.
- 키워드 인자 처리: Ruby의 키워드 인자는 인자 순서 재정렬 및 C 함수 호출 시 변환 등으로 추가 비용과 객체 할당을 유발합니다.
Ruby로 Class#new 재구현 및 인라인화 전략
- 프리미티브 활용: initialize의 private 속성, BasicObject의 send 제약, allocate 몽키패치 문제 해결을 위해 새로운 Ruby 프리미티브를 도입했습니다. 이는 컴파일러가 특수 명령어를 삽입하여 객체 할당 및 private 메서드 호출을 가능하게 합니다.
- 컴파일러 인라인화: Class#new의 바이트코드를 new 호출 지점에 직접 삽입하도록 컴파일러를 변경했습니다. new 호출 감지 및 명령어 삽입, 런타임 예외 처리를 위한 가드 명령어를 추가합니다.
성능 측정 결과 및 단점
- 속도 향상: 인라인화된 Ruby 3.5는 Ruby 3.4 대비 일반 인자 사용 시 약 1.8배, 키워드 인자 사용 시 최대 6.2배(10개 인자 기준) 빠른 성능을 보였습니다. 최소 1.4배의 성능 향상이 확인되었습니다.
- 단점: 메모리 사용량이 증가하고(약 1222배 증가), 스택 트레이스 변경이 발생하지만, 이는 수용 가능한 수준으로 평가됩니다.