JWarmup

JEP draft: JWarmup precompile java hot methods at application startup

요약

JWarmup은 응용 프로그램 (요청)이 피크에 로드되고 JIT가 컴파일 작업을 시작하는 동시에 CPU 리소스에 대한 일반 Java 스레드와 경쟁하는 JIT 컴파일러 스레드로 인한 Java 응용 프로그램 예열 성능 문제를 극복합니다.
JWarmup은 워밍업 중에 Java 핫 메소드를 사전 컴파일하여 피크 시간 성능 저하를 성공적으로 개선 할 수 있습니다.

목표

시작시 Java 핫 메소드를 사전 컴파일하여 최대 성능을 더 빨리 달성하고로드 피크 시간에 Java 애플리케이션의 CPU 사용량을 줄이십시오.

비 목표

빠른 시작을 목표로하지 않습니다.
시작부터 최적으로 생성 된 코드를 갖는 것은 목표가 아닙니다.
나중에 다시 컴파일 할 수 있습니다.
원하는 핫 메소드가 모두 사전 컴파일된다는 보장이 없습니다.

성공 지표

동일한 응용 프로그램 실행에서 정상 실행시 컴파일 정보를 수집하여 파일로 기록하십시오.
다음으로이 기록 된 파일로 실행하여 로드 된 피크 시간 이전에 기록 된 핫 메소드를 원시 버전으로 컴파일하여 메소드가 먼저 인터프리터에서 실행되는 대신 빠른 고유 버전을 실행할 수 있습니다.
성공적인 실행은 예외 나 충돌을 일으키지 않아야합니다. 대신 정상적인 실행처럼 작동하고 CPU 사용량이 적을 때 실행해야합니다.

동기

J2 서버 컴파일러는 일반 Java 메소드를 원시 코드로 컴파일하기 위해 C2, JIT 서버 컴파일러가 런타임 중에 대상 메소드에서 수집 한 프로파일 링 된 데이터를 사용하고 원시 코드로 컴파일 될시기를 결정합니다.
대규모 Java 애플리케이션의 경우 일반적으로 짧은 시간 내에로드가 커지지 만 JIT 컴파일러가 빠른 기본 버전을 갖도록 핫 메소드를 컴파일합니다.
JIT 스레드는 컴파일 작업에 동시에 더 많은 CPU주기를 사용하므로 Java 응용 프로그램 스레드에 대한 CPU 리소스가 줄어 듭니다.
이러한 경우 응용 프로그램 처리량이 감소하고 응답 시간이 더 길어집니다.
문제를 극복하는 해결책은 실제 큰 부하가 발생하기 전에 핫 자바 메소드를 사전 컴파일하는 것입니다.

설명

JWarmup, 사전 실행 및 정상 실행을 활성화하는 두 단계가 있습니다.
사전 실행은 일반적으로 테스트를 위해 대량의로드 데이터로 실행됩니다.
사전 실행의 목적은 핫 자바 메소드의 컴파일 정보 (프로파일링 데이터)를 기록하고 디스크 파일에 데이터를 저장하는 것입니다.
정상적인 실행 중에 이전에 기록 된 파일을 실행되는 응용 프로그램은 JIT 스레드는 먼저 기본 버전으로 파일의 방법을 컴파일합니다.
따라서 이러한 메소드는 시작부터 인터프리터 모드 이외의 기본 버전에서 실행됩니다.
사전 실행시 클래스 초기화 순서도 기록되며이 데이터는 클래스 초기화 장애로 인한 컴파일 실패를 방지하는 데 사용됩니다.
응용 프로그램 클래스간에 클래스 종속성이 있으며 워밍업 컴파일을 위해 클래스 초기화 순서가 기록됩니다.
모든 클래스에 종속성이있는 것은 아니지만 기록 된 데이터를 사용하여 클래스로드 문제를 피할 수 있습니다.
예열 컴파일은 API 기능을 통해 VM 시작 예열 컴파일을 알리는 응용 프로그램의 알림으로 시작됩니다.
워밍업 컴파일은 대부분의 애플리케이션 클래스가 로드 된 시점에 시작해야하며 JWarmUp.notifyApplicationStartUpIsDone()과 같은 알림을 위해 API 함수를 사용하여 사용자가 제어합니다.

Flags:

-XX:+CompilationWarmUp this enables JWarmUp

-XX:CompilationWarmUpRecordMinLevel= set minimal record level

-XX:+CompilationWarmUpRecording this starts JWarmUp recording

-XX:CompilationWarmUpLogFile= this sets log file path

-XX:CompilationWarmupRecordTime= this sets time to flush log into file, default at vm exit

-XX:+PrintCompilationWarmUpDetail this prints detail information

Other flags: The pre-run with -XX:+CompilationWarmUpRecording plus setting recording file use -XX:CompilationWarmUpLogFile, also set how long it should record with –XX:CompilationWarmUpRecordTime, like: -XX:+CompilationWarmUpRecording –XX: CompilationWarmUpLogFile=”jwarmup.log” –XX: CompilationWarmUpRecordTime=1200 record compiling info for 1200 (s) and store the info into jwarmup.log

With the record file available, application with -XX:+CompilationWarmUp –XX:CompilationWarmUpLofFile=”jwarmup.log” Will precompile the recorded methods in the log file after startup.

대안

취리히의 스위스 연방 기술 연구소 (Suite Federal Institute of Technology)에서 학생의 학사 학위 논문(“Integrating Profile Caching into the HotSpot Multi-Tier Compilation System”)과 유사한 작업이 수행되었습니다.

Azul은 이전 실행의 컴파일 데이터를 재사용하는 기술이 준비 완료 되었다.

JDK 9부터 OpenJDK는 AOT (Ahead of Time) 컴파일을 가지고있어 자바 메소드를위한 네이티브 바이너리 버전을 생성 할 수 있습니다.
시작 성능을 향상시키고이 JEP의 문제점을 부분적으로 피할 수 있습니다.
그렇다면 왜 문제를 해결하기 위해 다른 기술을 개발해야합니까?

AOT는 Graal 컴파일러와 함께 JDK에서 작동합니다.
JWarmup은 C2와 같은 기존 JIT 컴파일러를 기반으로하므로 이전 JDK로 이식 될 수 있습니다.
AOT 및 기본 이미지에는 GC 정책 및 기타 VM 설정과 같은 런타임에 대한 제한이 있습니다.
JWarmup은 구현 방법에 따라 일치하지 않는 런타임 옵션을 지원할 수 있습니다.
JWarmup은 프로파일 데이터에 의해 구동됩니다. 따라서 AOT 컴파일러보다 더 최적화 된 코드를 생성하는 데 유용한 핫 메소드, 인라인 트리, 분기 프로파일 링을 알 수 있습니다.

이러한 생각을 바탕으로 JWarmup은 AOT를 보완한다고 생각합니다.

정상 실행은 사전 실행 테스트와 다르게 작동 할 수 있습니다.
프로파일 데이터가 정확하지 않기 때문에 일부 JWarmup 메소드가 최적화되지 않은 것으로 나타났습니다.
고부하 환경에서는 피해야합니다.
같은 이유로 JWarmup 메소드는 더 높은 컴파일러 레벨에서 생성 된 JIT 메소드만큼 최적화되지 않습니다.
로드 피크 시간 디 최적화가 발생하지 않도록 사용자가 디 최적화가 발생할 수있는시기를 제어 할 수있는 제어 플래그 (-XX : CompilationWarmUpDeoptTime =)가 있으며 한 번의 반복에서 최적화 해제 할 수있는 메소드 수 (-XX : + CompilationWarmUpDeoptNumOfMethodsPerIter)도 제어하십시오.
이러한 유연한 제어 플래그를 사용하면 피크 시간 이후 대략적인 시간을 선택하여 역 최적화를 수행 할 수 있습니다.

테스트

구현은 플랫폼 독립적이므로 모든 플랫폼에 적용됩니다.
JIT에 대한 기존 핫스팟 테스트 외에도이 JEP에 대한 여러 테스트 사례도 포함됩니다.

위험과 가정

기록 된 프로파일 링 정보를 기반으로 원시 코드를 생성하려면 C2 컴파일러 코드를 사용하십시오.
생성 된 코드는 C2에 의해 정상적으로 실행되는 컴파일 된 품질보다 좋지 않을 수 있습니다.
실제 응용 프로그램이 복잡하여 클래스 관계도 복잡하기 때문에 실행시 클래스로드 순서가 기록 된 순서 번호보다 크거나 같은 경우에만 클래스로드 순서가 기록됩니다.
클래스 로딩 장애로 인해 시작시 많은 메소드가 컴파일되지 않을 수 있습니다.

의존성

없음

참조