Warmup Class Load / JIT 계측 기록
Warmup Class Load / JIT 계측 기록
실행 목적
AppWarmup직접 호출 구간에서 추가로 로드되는Spring / RDB / Redis / Cache / 구현체 주변 클래스를 확인한다.- 웜업 전후로
class load,JIT compilation,inlining,code cache변화를 함께 계측한다. - 블로그 본문에 넣을 수 있는 공개 가능한 근거를 요약해 둔다.
실행 환경
- JDK:
OpenJDK 21.0.7 - 로컬 컨테이너:
- MySQL
- Redis
- 앱 실행 프로필:
local - 앱 기동 방식:
bootJar실행
실제로 수행한 작업
- 로컬 MySQL/Redis를 컨테이너로 기동했다.
- 앱을
local프로필로 실행했다. class+load*,compilation*,inlining*,codecache*로그를 동시에 수집했다.- 앱 로그에서
[Warmup] Starting warmup...와[Warmup] Warmup completed, application is ready사이를 잘라 웜업 구간을 분리했다. - 웜업 전/중/후 통계를 집계했다.
Warmup 구간
- Warmup 시작:
2026-03-21 11:58:53.291 - Warmup 완료:
2026-03-21 11:58:53.938 - Warmup 길이: 약
647ms
class load 집계
Warmup 전
- 총
25,395 구현 코드:1,688orm_query:4,123spring_rdb:908redis_lib:575
관찰:
- 핵심
Controller / Service / Repository / CacheService본체와 Spring bean/CGLIB 프록시는 대부분 startup 단계에서 이미 로드됐다. - 즉 웜업은 “구현체 본체를 처음 로드하는 단계”라기보다, 요청 경로를 실제로 한 번 실행하면서 공통 경로를 더 데우는 단계에 가까웠다.
- 실제 로그에서도 웜업 시작 시각보다 앞서 구현체와 프록시가 먼저 나타났다.
[2026-03-21T11:58:17.049+0900][info ][class,load] com.deartail.app.category.CategoryRepositoryImpl
[2026-03-21T11:58:17.053+0900][info ][class,load] com.deartail.app.component.service.ComponentServiceImpl
[2026-03-21T11:58:29.995+0900][info ][class,load] com.deartail.app.component.service.ComponentServiceImpl$$SpringCGLIB$$0
Warmup 중
- 총
1,351 orm_query:311redis_lib:273spring_rdb:40구현 코드:65
Warmup 중에는 Spring / RDB / Cache, Hibernate / QueryDSL, Redis / Lettuce, 그리고 구현 코드 주변 클래스가 함께 관찰됐다.
[2026-03-21T11:58:53.351+0900][info ][class,load] org.springframework.orm.jpa.EntityManagerHolder
[2026-03-21T11:58:53.354+0900][info ][class,load] org.springframework.jdbc.datasource.DataSourceUtils
[2026-03-21T11:58:53.373+0900][info ][class,load] io.lettuce.core.protocol.DefaultEndpoint
[2026-03-21T11:58:53.391+0900][info ][class,load] com.deartail.app.component.service.ComponentServiceImpl$getHome$1
관찰:
- 웜업이 실제로 추가로 당겨온 것은
Redis/Lettuce,Hibernate/QueryDSL,Spring transaction/jdbc/cache경로였다. - 우리 코드 쪽은 구현체 본체보다
lambda,DTO, 응답 모델, 정렬/코루틴 보조 클래스가 추가 로드됐다.
Warmup 후
- 총
140 - 대부분 shutdown/connection teardown 관련 클래스였다.
JIT compilation 집계
Warmup 중
- 총
712
Warmup 중 JIT compilation은 Spring transaction, QueryDSL, Jackson 같은 공통 경로가 중심이었다.
관찰:
- 웜업 중
com.deartail...구현체 메서드가 JIT compilation 상위권에 거의 보이지 않았다. - 이번 구조에서 JIT의 직접 수혜는
Spring / Hibernate / QueryDSL / Lettuce / Jackson경로에 더 먼저 나타났다.
inlining 집계
Warmup 중
- 총
5,053
Warmup 중 실제 JIT 로그 발췌:
[2026-03-21T11:58:53.386+0900][debug][jit,compilation] com.querydsl.core.types.Templates::add
[2026-03-21T11:58:53.387+0900][debug][jit,inlining] com.querydsl.core.types.TemplateFactory::create callee is too large
[2026-03-21T11:58:53.626+0900][debug][jit,compilation] org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource::getTransactionAttribute
[2026-03-21T11:58:53.637+0900][debug][jit,inlining] org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource::getCacheKey inline (hot)
[2026-03-21T11:58:53.664+0900][debug][jit,compilation] org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut::matches
[2026-03-21T11:58:53.664+0900][debug][jit,inlining] org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource::getTransactionAttribute already compiled into a big method
[2026-03-21T11:58:53.854+0900][debug][jit,compilation] com.fasterxml.jackson.databind.JavaType::getRawClass
관찰:
- 인라인도 주로 Spring core / transaction / QueryDSL / JDK 공통 경로에서 활발하게 나타났다.
- 웜업 한 번으로 도메인 메서드 자체가 대거 최적화되는 그림은 아니었다.
code cache 스냅샷
Warmup 직전 마지막 관찰값:
non-profiled nmethods:11,694KBprofiled nmethods:36,504KBnon-nmethods:1,992KB
Warmup 중 마지막 관찰값:
non-profiled nmethods:11,487KBprofiled nmethods:33,359KBnon-nmethods:2,032KB
Warmup 후 마지막 관찰값:
non-profiled nmethods:11,718KBprofiled nmethods:33,464KBnon-nmethods:2,034KB
주의:
code cache used값은 sweep/deoptimization 영향으로 단순 누적처럼 증가하지 않을 수 있다.- 여기서는 절대값보다
웜업 창 안에서도 코드 캐시 활동이 있었다는 근거로 보는 편이 안전하다.
해석
- Warmup 전에 이미 핵심
Controller / Service / Repository / CacheService구현체와 CGLIB 프록시 상당수는 startup 단계에서 로드된다. - Warmup이 추가로 소진하는 비용은
Redis/Lettuce,Hibernate/QueryDSL,Spring transaction/jdbc/cache, 그리고lambda/DTO/응답 모델같은 요청 경로 주변 클래스가 중심이다. - Warmup 창 안에서도 JIT compilation과 inlining은 분명히 발생한다.
- 하지만 이번 구조에서 JIT의 주된 대상은
우리 비즈니스 메서드보다Spring / Hibernate / QueryDSL / Redis / Jackson경로에 가깝다. - 따라서 글의 핵심 메시지는 여전히
요청 경로의 초기화 지연을 고객 요청 전에 미리 소진한다가 맞고, JIT는 그 위에 따라오는 보조 효과로 설명하는 편이 정확하다.