Java

[JVM 밑바닥까지 파헤치기] 11-2. 백엔드 컴파일과 최적화: JIT 컴파일러

noahkim_ 2024. 12. 25. 05:28

저우즈밍 님의 "JVM 밑바닥까지 파헤치기" 책을 정리한 포스팅 입니다

 

1. 적시 컴파일러

  • 핫코드들을 탐지하여 컴파일하고 최적화하여 실행 효율을 높임

 

2. 내장 컴파일러

구분 특징
목적/사용 시점
클라이언트 컴파일러 (C1) 빠른 컴파일 속도
기본적인 최적화 적용
GUI 프로그램
빠른 응답성 중시
서버 컴파일러 (C2) 상대적으로 느린 컴파일
복잡하고 고급 최적화 수행
- 죽은 코드 제거, 범위 검사 제거, null 검사 제거
- 루프 언롤링, 루프 호이스팅
서버 환경
장시간 실행되는 애플리케이션 최적화

 

3. 계층형 컴파일

  • 서버 모드의 기본 컴파일 전략
계층 컴파일러 종류 프로파일링 최적화 수준 설명
0 없음 (인터프리터)
초기 실행.
빠른 시작을 위한 인터프리터 실행
1 클라이언트 컴파일러(C1) 기본 최적화
간단한 최적화로 빠른 컴파일
2 클라이언트 컴파일러(C1) 기본 프로파일링 중간 수준 최적화
일부 프로파일링 정보 기반 최적화
3 클라이언트 컴파일러(C1) 모든 프로파일링 고급 최적화
충분한 정보 수집 후 컴파일
4 서버 컴파일러(C2) 모든 프로파일링 최상위 수준의 최적화
장기 실행되는 코드에 사용됨

 

4. 컴파일 대상과 촉발 조건

핫코드

  • 자주 실행되는 메서드나 코드 블록
  • JIT 컴파일러의 주요 최적화 대상

 

핫스팟 코드 탐지

탐지 방식 설명 특징
샘플 기반 실행 중인 스레드의 호출 스택을 일정 주기로 샘플링
스택 상단에 자주 나타나는 메서드를 핫코드로 판단
성능 부담 적음
정확도는 낮을 수 있음
카운터 기반 메서드 또는 코드 블록에 카운터를 부여하고 실행 횟수 누적
임계값 초과 시 핫코드로 판정
정확함
약간의 오버헤드 발생
백 에지 카운터 기반 루프의 반복 횟수를 추적
특정 루프가 자주 반복되면 해당 루프를 포함한 메서드를 핫코드로 간주
루프 최적화 유도
온스택 치환(OST) 트리거용

 

5. 컴파일 과정

비동기 기반

  • 컴파일은 백그라운드에서 비동기로 진행됨
  • 컴파일이 완료되면, 메서드의 호출 진입점 주소가 자동으로 새 값으로 덮여짐

 

과정

  1. HIR 생성 (High-level Intermediate Representation)
    • 바이트코드로부터 생성됨 (타깃 독립적 중간 표현)
    • 정적 단일 할당 기반 표현
    • 최적화 구현을 도움
  2. HIR 최적화
    • null 검사 제거, 범위 검사 제거 등
  3. LIR 생성 (High-level Intermediate Representation)
    • CPU 아키텍처에 더 가까운 수준의 중간 표현
  4. 네이티브 코드 생성
    • LIR로부터 머신 코드 생성
    • 선형 스캔 레지스터 할당: 제한된 CPU 레지스터 자원을 효율적으로 배정
  5. 핍홀 최적화
    • 인접한 명령어들을 분석하여 병합, 제거 또는 재구성

 

6. 환경변수

옵션 설명
-Xint
인터프리터(해석) 모드로만 실행 (JIT 비활성화)
-Xcomp
컴파일 모드로만 실행 (모든 메서드를 즉시 컴파일)
-XX:CompileThreshold=<n>
카운터 기반 핫코드 탐지 시, 컴파일 문턱값 지정(기본값: 10,000회 호출 시 컴파일)
-XX:+BackgroundCompilation
백그라운드에서 비동기 JIT 컴파일 활성화
-XX:+PrintCompilation
메서드가 JIT 컴파일될 때 해당 메서드명을 출력 (디버깅/분석 용도)

 

7. 실행 모드

  • jvm 버전, 호스트 머신의 하드웨어 성능에 맞춰 자동으로 선택됨