jit-compiler

2 개의 포스트

datadog4분 읽기큐레이션 요약

접두사 트라이를 JVM 상수로 인코딩해 APM Java 시작 시간을 개선한 방법

애플리케이션 시작 시간은 사용자 경험, 개발 생산성, 클라우드 비용에 모두 영향을 주며, Java APM의 클래스 매칭 비용도 주요 요인이다. Datadog은 JVM 시작 단계의 제약을 고려해 클래스명 접두사 매칭을 최적화했고, 최근 4년간 관련 오버헤드를 30% 줄였다. 특히 여러 접두사 매칭 트라이(trie)를 하나의 JVM 문자열 상수로 미리 인코딩해, 시작 시 별도의 파일 읽기나 자료구조 구축 없이 빠르게 조회하도록 만든 것이 핵심이다. ## Java APM과 클래스 계측 - Java Instrumentation API는 클래스가 로드되기 전에 변환할 수 있어, 네이티브 코드가 필요한 JVMTI보다 Java 기반 APM 구현에 적합하다. - APM은 메서드 시작·종료 시점 기록, 호출 간 컨텍스트 전파 등을 위해 클래스에 코드를 삽입한다. - 개별 메서드 계측 비용은 작지만, 모든 클래스와 메서드를 계측하면 전체 성능 비용이 급격히 증가한다. - 따라서 관측 가치가 높은 클래스만 선별해야 하며, 이 선별 과정이 **클래스 매칭**이다. ## 클래스명 접두사로 탐색 범위 줄이기 - 일반적인 Java 애플리케이션은 수만 개의 클래스를 정의하고, 대규모 엔터프라이즈 애플리케이션은 10만 개 이상을 로드할 수 있다. - 클래스 파일을 분석하거나 상속 구조를 확인하는 방식은 비용이 크다. - 클래스 파일 파싱이 필요하다. - 관련 타입의 추가 클래스 파일을 읽어야 할 수 있다. - 이에 따라 Datadog APM은 먼저 클래스명과 패키지명 접두사를 curated ignore list와 비교해 계측 대상이 아닌 클래스를 빠르게 제외한다. - 이 초기 접두사 매칭은 모든 클래스에 적용되므로, 작은 알고리즘 개선도 전체 시작 시간에 측정 가능한 영향을 준다. ## JVM 시작 단계의 특별한 제약 - 에이전트는 애플리케이션의 `main`보다 먼저 실행되는 `premain` 단계에서 클래스 변환기를 등록한다. - 이 시점에는 다음과 같은 제약이 있다. - 로드된 클래스가 거의 없다. - JIT 컴파일러가 아직 준비되지 않았다. - Java 8에서는 `premain` 이후에야 JIT가 시작되므로 코드가 인터프리트되고 최적화되지 않는다. - 일부 JDK API 호출이 애플리케이션 동작에 영향을 줄 수 있다. - 예를 들어 `java.util.logging`을 사용하면 `LogManager`가 초기화된다. - 이후 애플리케이션의 `main`에서 사용자 지정 `java.util.logging.manager`를 설정하려 해도 이미 초기화가 끝났기 때문에 동작이 깨질 수 있다. - 따라서 `premain`에서는 외부 리소스, 무거운 라이브러리, 부작용이 있는 JDK API 사용을 피해야 한다. ## 기존 코드 기반 매칭의 한계 - 2020년 당시 Datadog APM Java는 복잡한 중첩 구조의 코드를 직접 생성해 접두사를 매칭했다. - 이 방식은 유연했지만 다음 문제가 있었다. - 매칭 규칙을 유지보수하기 어려웠다. - Java 8의 초기화 단계에서는 JIT 최적화를 기대할 수 없었다. - 시작 시 빠르게 실행되도록 여러 추가 최적화가 필요했다. - 분석 결과, 기존 매칭 규칙에는 트라이 자료구조가 가장 적합한 대안으로 판단됐다. - 하지만 일반적인 트라이는 리소스 파일을 찾고, 읽고, 파싱한 뒤 노드를 구성해야 하므로 `premain` 환경에 적합하지 않았다. ## 트라이를 JVM 문자열 상수로 인코딩 - Datadog은 `ClassNameTrie`라는 접두사 트라이를 만들고, 이를 하나의 JVM 문자열 상수로 표현했다. - 문자열 상수는 클래스 로딩 과정에서 JVM이 직접 로드하므로 다음 장점이 있다. - `ldc` 단일 바이트코드 명령으로 접근할 수 있다. - 파일 검색이나 I/O가 필요 없다. - 클래스 내부에 포함되므로 애플리케이션 패키징·재패키징 후에도 유지된다. - 데이터가 작고 연속적으로 저장되어 캐시 지역성이 좋다. - 시작 단계에 트라이 객체를 별도로 생성할 필요가 없다. ## 문자열 내부의 트라이 구조 - Java의 `char`는 2바이트이며 65,536개의 값을 표현할 수 있다. - 이 값을 일반적인 문자뿐 아니라 트라이의 제어 정보와 매칭 결과 저장에도 사용한다. - 각 트라이 노드는 다음 구조를 가진다. - 첫 번째 문자: 해당 노드의 브랜치 개수 - 이어지는 문자들: 각 브랜치의 문자 - 브랜치 문자 뒤의 값 문자들: 각 브랜치의 결과 정보 - 브랜치 문자는 정렬되어 저장되므로 이진 검색으로 빠르게 다음 경로를 찾을 수 있다. - 값은 상위 비트에 따라 세 가지 의미를 가진다. - **Leaf**: 확정된 결과이며 검색을 즉시 종료한다. - **Bud**: 잠정적인 결과를 제공하지만 더 긴 접두사를 확인하기 위해 검색을 계속한다. - **Inline segment 길이**: 해당 브랜치에 이어지는 문자열 구간의 길이를 나타낸다. - Bud와 leaf에는 glob 비트를 설정할 수 있다. - 기본적으로 결과는 입력 키가 해당 노드에서 정확히 끝날 때만 적용된다. - glob 비트가 있으면 뒤에 문자가 더 남아 있어도 결과를 적용할 수 있다. - 이 비트 구성 때문에 `ClassNameTrie`에 저장할 수 있는 최대 값은 8,191이다. ## 실용적인 결론 JVM의 가장 이른 시작 단계에서 실행되는 코드는 JIT 최적화나 일반적인 런타임 자료구조 생성에 의존하기 어렵다. 이런 환경에서는 작은 매칭 데이터라도 문자열 상수처럼 JVM이 직접 로드할 수 있는 형태로 미리 인코딩하면 초기화 비용과 I/O를 줄이고, 대규모 클래스 탐색의 누적 비용을 낮출 수 있다.

원문 읽기(새 탭에서 열림)
naver원문

네이버 TV (새 탭에서 열림)

JVM 기반 웹 애플리케이션은 실행 초기 JIT(Just-In-Time) 컴파일러의 최적화 과정에서 발생하는 응답 지연 문제를 해결하기 위해 '웜업' 과정이 필수적입니다. 기존의 API 호출식 웜업은 데이터 오염이나 외부 시스템 부하와 같은 부작용을 초래할 수 있으나, 본 발표에서는 이를 극복하기 위해 핵심 라이브러리만을 직접 예열하는 '라이브러리 웜업' 방식을 제안합니다. 이 기술을 통해 부작용 없이 애플리케이션 배포 직후의 성능을 안정적으로 확보할 수 있습니다. **JVM 웜업의 필요성과 기존 방식의 한계** * JVM은 실행 초기에 인터프리터 방식으로 동작하다가, 반복되는 코드를 JIT 컴파일러가 네이티브 코드로 최적화하는 과정을 거치며 성능이 올라갑니다. * 이 최적화가 완료되기 전까지는 응답 시간이 길어지거나 CPU 사용량이 급증하는 현상이 발생하므로, 실제 트래픽이 들어오기 전 코드를 미리 실행하는 웜업이 필요합니다. * 기존의 API 호출 방식은 가짜 요청을 보내는 과정에서 DB 데이터 정합성을 해칠 수 있고, 외부 API 호출에 따른 불필요한 연동 부하를 발생시키는 단점이 있습니다. **라이브러리 웜업의 핵심 아이디어와 구현** * 비즈니스 로직 전체를 수행하는 대신, 애플리케이션에서 성능 비중이 크고 공통적으로 사용되는 '라이브러리 코드'만을 타겟팅하여 예열합니다. * 예를 들어 JSON 파싱, 암호화, 복잡한 수치 계산 모듈 등 JIT 컴파일 임계치(Threshold)를 넘겨야 하는 핵심 메서드들을 반복 호출하도록 설계합니다. * 애플리케이션 시작 단계(Post-Construct 등)에서 비즈니스 로직과는 독립된 웜업 코드를 실행함으로써 데이터 오염의 위험을 원천적으로 차단합니다. **성능 검증 및 실무적 이점** * 라이브러리 웜업 적용 후, 배포 초기에 발생하는 응답 속도의 '튀는 현상(Spike)'이 현저히 감소하고 전체적인 레이턴시가 안정화됨을 확인했습니다. * API 호출 방식보다 구현이 단순하고 외부 의존성이 적어 관리가 용이하며, 배포 파이프라인의 안정성을 높이는 데 기여합니다. * 다만, 모든 비즈니스 경로를 커버하지는 못하므로 성능 영향도가 높은 핵심 모듈을 선별하여 집중적으로 웜업하는 전략이 유효합니다. 빠른 스케일 아웃이 필요한 마이크로서비스 환경이나 지연 시간에 민감한 실시간 서비스라면, API 기반 웜업의 대안으로 이와 같은 라이브러리 단위의 정밀한 웜업 도입을 적극 권장합니다.