AOT(Ahead-Of-Time) 컴파일러
AOT Compiler
프로그램 실행(런타임) 이전에 최적화(C1, C2) 와 네이티브 코드 생성(인터프리터, C1, C2)를 미리 하여 런타임에는 바이트코드를 바로 실행하게 할 수 있다.
미리 자바 코드로 부터 네이티브 코드를 만드는 컴파일러르 AOT 컴파일러라 한다.
java 진영에서는 크게 두가지 컴파일러가 존재한다.
AOT vs JIT
JIT 의 단점
- 계층형 JIT 에서는 최종 단계인 C2 까지 가기 오래 걸린다. 인터프리터 -> C1 -> C2 순이다.
- 호출 횟수가 부족하면 C1 조차 사용하지 못할 수 있다.
- C2 최적화는 런타임에 컴퓨팅 자원을 소모한다. 결국 유저가 쓸 컴퓨터를 뺏어쓴다.
- 유저가 쓸 컴퓨팅 자원을 뺏어 쓰기 때문에, 오래 걸리는 최적화 작업은 하지 못한다.
- 예를 들어 전체 프로그램을 대상으로 하는 최적화인 프로시저 간 분석은 아주 오래 걸린다. JIT 는 이 분석의 일부분만 수행할 수 있다.
- 또한 확실한 증거가 아닌 모니터링을 통한 가정을 통해 공격적인 최적화를 한 후 가정이 틀리면 인터프리터로 돌아가는 형태를 띤다. 이것도 런타임에 정확한 최적화를 하기엔 시간이 너무 많이 걸리기 때문이다.
최종 결과물의 코드 실행 속도가 JIT 가 AOP 보다 느린게 아니다.
결국 JIT 도 오래 실행되면 C2 컴파일의 결과로 충분히 최적화된 빠른 코드가 실행된다. 후술하겠지만 오히려 AOT 에서 할 수 없는 최적화도 가능하다.
다만 JIT 는 일정 호출 횟수가 지나야 최적화된 코드가 실행된 다는 것과 바이트 코드를 해석과 최적화를 런타임에 해야 한다는 것이 느리게 하는 요인(과정에 대한 이야기)인 것이다.
AOT 의 장점
- 애플리케이션 실행 전에 최적화를 실행한다. 따라서 오래 걸리는 최적화(ex. 코드 전체를 분석해야 하는 최적화) 도 부담없이 가능하다.
- 네이티브 코드를 미리 만들어 놓으므로, 애플리케이션 시작시 최적화된 코드가 바로 실행된다.
- 애플리케이션 시작 시간 자체도 줄어든다. 바이트 코드 해석 작업이 필요 없기 때문이다.
- (JVM 에 비해) 메모리 사용량이 적다.
JIT 의 장점
- 모니터링 기반의 최적화
- 객체의 (추상 클래스의)실제 타입, 주로 선택되는 조건 분기, 메서드 호출시 주로 호출되는 버전, 루프문의 반복 횟수 등은 런타임에 실제 호출을 분석하지 않고서는 모르는 정보들이다.
- 이런 정보들로 핫코드를 특정한뒤 최적화는 AOT 에서는 하지 못한다.
- 예측 최적화
- AOT 의 경우 미리 네이티브 코드가 만들어진다. 런타임에 해석을 다시 하고 그런거 없다.
- 반면 JIT 의 경우 모니터링 결과로 예측 최적화를 한 후 예측이 틀렸다면 인터프리터로 돌아갈 수 있다. 따라서 AOT 에 비해 더 급진적인 예측 최적화가 가능하다.
- 링크 타임 최적화
- 예를 들어 각자 컴파일된 AOT 이미지를 조합하여 애플리케이션을 구동한다 했을때, 각자 컴파일된 AOT 이미지의 클래스들은 서로를 알지 못한다. 반면 JIT 는 동적으로 클래스를 로딩하여 구동할 때 따로 컴파일된 바이트 코드라도 JIT 는 두 클래스를 조합하여 최적화가 가능하다.
AOT 의 단점
- AOT 는 클래스 라이브러리를 동적으로 읽어들일 순 없다.
- AOT 는 코드 양이 많다(바이트 팽창)
- AOT 는 플랫폼 중립성이 없다. 하드웨어와 운영체제별로 다시 만들어야 한다.
AOT Compile 의 형태
- 애플리케이션 전체를 미리 네이티브 코드로 컴파일한 후 실행하는 방법
- ex) 현재 GraalVM 의 native-image
- 애플리케이션에 쓸 라이브러리를 미리 컴파일 한 후 공유
- ex) 과거 jaotc
- ex) 현재 GraalVM Shared-Lib(참고)
AOT 실 사용 예
- MSA
- 크기가 작음, 높은 빈도의 개발 및 배포
- 미리 최적화된 바이트 코드가 있다면 굳이 계층형 컴파일러의 소요 시간을 기다릴 필요 없이 최적화된 코드를 빨리 실행할 수 있음.
- 공용 클래스 파일을 미리 로드해두는 AppCDS 와 비슷하게 Pre-Compiled Shared Library 만드는 용도.
뭐가 더 좋음?
JVM 에서 AOT 는 좀 더 최근에 개발되는 신기술 축에 속하지만 그렇다고 더 좋은건 아니다.
joatc 컴파일러는 JDK 9 에 들어와서 JDK 17 에 빠지고 GraalVM 에 편입된 후
최근에는 Galahad 프로젝트로 GraalVM 다시 JDK 에 들어올 시도를 하고 있다.
JIT, AOT 중 모든 상황에서 이게 좋다! 는 없으며, 위 장단을 잘 따져서 애플리케이션 특성에 맞게 프로파일링 후 AOT 를 도입할 수 있을 것이다.