[Spring Boot] JVM Cold Start 최적화하기

이동엽·2024년 6월 23일
5

spring

목록 보기
19/21

1. 개요

Kakaopay 기술블로그: Google Cloud Serverless for Java developer 글을 읽고,
JVM Cold Start 완화 방법에 대해 정리한 내용입니다.

원본 글에서 아래의 내용을 추가하였습니다.

  • GC 종류 별 적용 방법
  • 제시된 여러 방식에 대한 적용 전후 비교
    • 테스트 대상
      • C2 컴파일러 비활성화 전후 비교
      • CDS 적용 전후 비교
      • CRaC 적용 전후 비교
      • GraalVM으로 AOT 컴파일 적용 전후 비교
      • OpenJDK Project ‘Leyden’ 적용 전후 비교
    • 테스트 환경
      • MacBook Air M1, 메모리 16GB, 8코어
      • Spring Boot 3.2.1 & JDK 17 & G1 GC
      • 비교 방식 : 동일한 스프링부트 프로젝트 실행시 출력되는 로그로 JVM 기동 시간 비교
        • Started <ApplicationName> in X seconds (process running for Y)
        • X : JVM 초기화, Spring 컨텍스트 초기화, 애플리케이션 설정 로드, 빈 생성 등의 시간
        • Y : JVM 초기화와 함께 OS 레벨의 프로세스 시작 시간도 포함

2. JVM Cold Start 최적화

2-1. 최신 버전 사용 및 GC 튜닝하기

프로젝트에서 큰 변화 없이 단순히 최신 JDK 버전으로 사용하기만 해도 성능 향상이 있습니다.

JVM은 시작하는 단계에서 동적 로딩, 지연 초기화 등으로 인해 많은 연산이 수행됩니다.

이 과정에서 GC도 종종 발생하기 때문에, 환경에 따른 적절한 GC를 선택하는 것도 방법일 수 있습니다.


JDK 17과 21에서는 G1 GC가 기본으로 적용됩니다. JDK 17부터 출시된 ZGC의 경우는 대용량을 처리해야 하는 상황일 경우에 성능이 좋다고 합니다. 자세한 기준은 아래 표를 참고하시면 됩니다.


각각의 GC 적용 방법

java -jar -XX:+Use{사용할 GC 이름} {프로젝트이름}.jar

위와 같이 java -jar 명령어로 실행시, 각 GC별로 아래의 옵션을 추가하시면 됩니다.

  • -XX:+UseG1GC
  • -XX:+UseZGC
  • -XX:+UseParallelGC
  • -XX:+UseSerialGC
  • -XX:+UseShenandoahGC

2-2. C2 컴파일러 비활성화하기

JVM은 JIT(Just In Time) 컴파일러를 이용해 컴파일 수준(Level)을 나누고, 각 수준에 맞춰 다른 컴파일러가 동작합니다. 이때, 각각의 컴파일러는 다른 목표를 가지고 있습니다.

  • C1 컴파일러 : 빠르게 컴파일 완료하여 애플리케이션의 성능을 향상
  • C2 컴파일러 : 자주 사용하는 코드를 네이티브 코드로 변환하여 성능을 향상
    • → 정교한 최적화 기법을 사용하기에, 컴파일 시간과 리소스 사용이 많아 오버헤드가 발생할 수 있음.

C2 컴파일러 비활성화 적용하기

다만, 단순한 서비스나 C1 컴파일로 성능을 만족하는 경우에는 C2 컴파일러를 사용할 필요가 없습니다.

따라서 아래의 옵션을 사용하여 C1 컴파일러만 동작하도록하여 Cold Start를 완화시킬 수 있습니다.

java -jar -XX:TieredStopAtLevel=1 {프로젝트이름}.jar

TieredStopAtLevel 레벨 설명

  • 0 : Interpreted Code
  • 1: Interpreted Code
  • 2 : Limited C1 Compiled Code
  • 3 : Full C1 Compiled Code (기본값)
  • 4 : C2 Compiled Code

적용 전 실행시간 : 2.488초


적용 후 실행 시간 : 2.402초


2-3. CDS 적용하기

CDS(Class Data Sharing)는 클래스를 로딩하는 과정에서 로컬 공유 아카이브에 저장된 CDS 파일(.jsa)을 참조하여 기동 하는 방식입니다.

자주 사용하는 클래스의 메타데이터(클래스 구조, 메소드, 필드 등)들이 CDS 파일을 저장하면 시작 시간을 효과적으로 줄일 수 있습니다.


기본 CDS 아카이브 생성하기

아래 명령어는 기본 위치인 JAVA_HOME/lib/server/classes.jsa에 기본 아카이브를 생성합니다.

java -Xshare:dump

사용자 지정 아카이브 생성하기

아래 명령어는 해당 명령어를 실행한 위치에 MyApp.jsa 아카이브를 생성합니다.

java -XX:ArchiveClassesAtExit=MyApp.jsa -cp MyApp.jar MyMainClass

실행 시간 : 2.248초


사용자 지정 아카이브 사용하기

java -XX:SharedArchiveFile=MyApp.jsa -cp MyApp.jar MyMainClass

실행 시간 : 2.107초


2-4. CRaC 적용하기

CRaC(Coordinated Restore at Checkpoint)는 기동 중인 애플리케이션을 중단한 채로 저장해두고,

트래픽이 유입되어 추가 애플리케이션이 필요할 때 복원하는 방식입니다.


이를 위해서 체크포인트라고 하는 인스턴스의 현재 상태를 파일로 저장합니다. 가장 큰 장점은 하나의 체크포인트로 여러 개의 인스턴스를 복원할 수 있다는 점으로, 트래픽 폭증 시 빠른 확장에 적절할 것 같습니다.


CRaC 사용 시 고려 사항

  • Spring Boot 3.2부터 CRaC를 지원 : 아직은 초기 단계이므로 실 서비스에서는 주의 필요
  • CRIU 기술 기반으로, Linux 실행 환경에서만 사용 가능
  • 체크포인트를 언제 하는지에 따라 서비스의 성능이 달라짐
  • 복원 시 여러 리소스들을 재구성하는데 이 과정에서 호환성 이슈로 지연이나 실패가 발생 가능

CRaC 실행하기


2-5. GraalVM으로 AOT 컴파일 적용하기

오라클은 앞에서 말한 C2 컴파일러를 대체하는 Graal 컴파일러를 만들었습니다.


Graal 컴파일러의 특징

  • Java, JavaScript, Python, Ruby 등의 다양한 언어를 지원
  • JVM 없이 GraalVM에서 실행 가능한 네이티브 이미지를 생성
  • 코드를 분석해서 필요한 부분만 한정적으로 컴파일함 → 자원을 효율적으로 사용하고 빠른 속도가 보장
  • AOT(Ahead-of-Time) 컴파일을 지원



Graal 컴파일러의 단점

  • AOT Compilation으로 인해사용하면 런타임시간을 많이 줄일 수 있지만, 컴파일 시점에 런타임 시 동적으로 생성되는 클래스들까지 미리 컴파일을 한다.
    • →Java가 가진 일부 동적 기능(Reflection, Dynamic Proxy 등)을 사용하는 데 제약을 받게 됨.
  • 특정 3rd party library는 GraalVM에서 기동하지 못한다는 단점이 있었다.


GraalVM 기반 컨테이너 이미지 만들기


2-6. OpenJDK Project ‘Leyden’ 적용하기

Leyden은 Serverless, Cloud 환경에서 애플리케이션 최적화를 위해 시작된 OpenJDK 프로젝트입니다.

성능을 최적화하기 위해 CDS, Graal 컴파일러를 활용한 AOT Compilation, GraalVM의 SubstrateVM 기술을 포함한 모든 Java 리소스를 검토하고 있다고 합니다.


Framework에는 Startup 최적화를 위해 GraalVM의 SubstrateVM 기술을 활용하여, 애플리케이션 코드를 네이티브 바이너리로 변환하는 Spring AOT가 존재합니다.

Premain 최적화를 적용하여 시작 시간을 기존보다 2~4배 단축할 수 있는 것을 확인했다는 자료도 있습니다.


3. 마무리

첫번째로 나온 최신 JDK 사용 및 GC 튜닝하는 방법을 제외하고는 전부 처음보는 방법이였어서 새로운 접근 방식으로 다가와 신선했습니다.

CRaC와 GraalVM의 경우, 쿠버네티스와 같은 컨테이너 기술에 대한 지식이 부족하여 아쉽게도 직접 비교를 해보지는 못했습니다.

그래도 앞으로 계속 새로운 최적화 방법들이 나올 예정이니 계속해서 관심을 가져야겠습니다.


4. 참고자료

profile
백엔드 개발자로 등 따숩고 배 부르게 되는 그 날까지

1개의 댓글

comment-user-thumbnail
2024년 6월 24일

어떤 인생을 살고있는거냐 동엽아...
화이팅이다!!

답글 달기