JRuby의 JDK 25 AOTCache를 활용한 시작 시간 최적화

JRuby and JDK 25: Startup Time with AOTCache

작성자
HackerNews
발행일
2025년 09월 24일

핵심 요약

  • 1 JDK 25에 도입된 AOTCache는 JRuby의 고질적인 시작 시간 문제를 획기적으로 개선하는 핵심적인 기능을 제공합니다.
  • 2 `--dev` 모드, AppCDS, 그리고 AOTCache를 순차적으로 적용하여 JRuby의 기본 시작 시간을 943ms에서 423ms로 50% 이상 단축하는 데 성공했습니다.
  • 3 Project Leyden의 AOT 컴파일 및 최적화 기능이 추가되면 JRuby는 병렬 처리, 세계적 수준의 GC, 빠른 성능과 더불어 빠른 시작 시간까지 갖춘 최고의 Ruby 구현이 될 잠재력을 보여줍니다.

도입

JDK 25는 JDK 21 이후의 최신 LTS 릴리스로, JVM 수준에서 여러 놀라운 기능을 제공합니다. 본 게시물은 JRuby와 같은 명령줄 생태계에서 가장 중요한 개선 사항 중 하나인 AOTCache(Ahead-of-Time Cache)와 미래 실행을 위한 코드 사전 최적화 기능에 대해 다룹니다. JRuby의 시작 시간 과제부터 시작하여 AOTCache가 JRuby 워크플로우 속도를 어떻게 향상시킬 수 있는지 탐구하고, JDK 25 릴리스에는 포함되지 않았지만 "곧 출시될" 기능들까지 살펴봅니다.

JRuby의 시작 시간 최적화는 오랜 과제였으며, 다양한 기술을 통해 점진적으로 개선되어 왔습니다.

JVM에서의 빠른 시작 시간 과제

JRuby는 Ruby 애플리케이션이 매번 컴파일되지 않은 소스에서 시작하고, JRuby 및 JVM 내부 코드가 지연 최적화 방식을 사용하며, JDK 자체도 Java로 작성되어 최적화에 시간이 소요되는 등의 이유로 시작 시간이 느립니다. 예를 들어, JDK 21에서 jruby -e 1 명령은 943ms가 소요되며, 이는 CRuby의 45ms에 비해 현저히 느립니다. 하지만 JVM이 최적화를 시작하면 JRuby의 실제 성능을 확인할 수 있습니다. gem list 명령을 반복 실행하면 첫 실행에 1초 이상이 소요되지만, 이후 실행에서는 0.3초대까지 단축됩니다.

시작 시간 개선 기법

JRuby의 시작 시간을 개선하기 위해 여러 기법이 적용되었습니다.

  • 기법 #1: 작업량 줄이기 (--dev 플래그) --dev 플래그는 JRuby의 바이트코드 컴파일러와 JVM의 2단계 프로파일링 최적화를 비활성화하여 불필요한 최적화를 건너뜁니다. 이를 통해 jruby -e 1 실행 시간이 941ms에서 723ms로 단축됩니다.

  • 기법 #2: AppCDS (Application Class Data Sharing) AppCDS는 JVM 클래스 로딩 및 처리의 초기 부팅 작업을 저장하여 향후 실행 시 해당 처리를 제거합니다. AppCDS를 사용하면 jruby -e 1이 702ms로, --dev 모드와 함께 사용 시 567ms로 단축됩니다. gem list 명령의 경우 AppCDS 적용 시 1.397초, --dev 모드와 함께 사용 시 0.967초로 개선됩니다.

  • 기법 #3: JDK 업그레이드 (JDK 21 -> JDK 25) JDK 21에서 JDK 25로 업그레이드하는 것만으로도 gem list 실행 시간이 1663ms에서 1546ms로 소폭 개선되는 등 전반적으로 미미한 성능 향상이 있었습니다.

  • 기법 #4: 실행 간 최적화 데이터 저장 (AOTCache) JDK 25의 AOTCache는 AppCDS를 대체하는 주요 메커니즘으로, 훈련 실행을 통해 최적화 프로필을 저장하여 향후 실행 시 최적화를 돕습니다. 훈련 후 AOTCache를 사용하면 jruby -e 1이 581ms로, --dev 모드와 함께 사용 시 518ms로 단축됩니다. gem list는 AOTCache 적용 시 1.152초, --dev 모드와 함께 사용 시 0.861초로 단축되며, gem list 훈련을 통해 0.825초까지 기록했습니다.

  • 기법 #5: 최적화된 코드 저장 (Project Leyden EA2) Project Leyden의 초기 액세스 빌드에는 AOT 컴파일된 네이티브 코드, 동적 프록시 및 리플렉션 데이터, 클래스 검색 데이터 캐싱 기능이 포함되어 있습니다. Leyden EA2와 AOTCache를 사용하면 jruby -e 1이 462ms로, --dev 모드와 함께 사용 시 423ms로 단축됩니다. gem list는 1.035초로, --dev 모드와 함께 사용 시 815ms까지 단축되는 경이로운 결과를 보여주었습니다.

결론

이러한 노력과 최신 JVM 개선 사항을 통해 JRuby의 시작 시간은 획기적으로 향상되었습니다. 기본 시작 시간은 943ms에서 423ms로, `gem list`는 1663ms에서 815ms로 50% 이상 빨라졌습니다. JRuby 팀은 AppCDS에서 AOTCache로 자동 최적화 전환을 진행할 예정이며, Project Leyden 팀과의 협력을 통해 AOTCache를 더욱 개선할 계획입니다. 진정한 병렬 처리, 세계적 수준의 가비지 컬렉션, 빠른 직선 성능을 시작 시간 저하 없이 누릴 수 있는 JRuby의 미래가 기대됩니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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