JIT 컴파일 (JIT Compiling)
A.1) JIT 컴파일이란?
JIT(Just-In-Time) 컴파일은 프로그램 실행 중, 즉 런타임에 코드를 컴파일하는 방식입니다. 이는 프로그램 실행 전에 미리 컴파일하는 전통적인 방식과는 다릅니다. 주로 소스 코드나 바이트코드 (bytecode) 를 기계어 (machine code) 로 변환하여 바로 실행할 수 있도록 합니다.
A.2) 동작 원리
A.2.1) 바이트코드 (Bytecode) 란?
- 바이트코드는 소스 코드를 중간 단계의 표현으로 변환한 것으로, 특정 하드웨어에 종속되지 않으며 다양한 아키텍처에서 이식성 (portability) 을 가질 수 있습니다.
- 바이트코드는 보통 가상 머신 (Virtual Machine) 에 의해 해석되거나 실행됩니다.
A.2.2) JIT 컴파일 과정
- JIT 컴파일러는 프로그램의 바이트코드를 읽고 이를 동적으로 기계어로 변환합니다.
- 변환 단위: 파일 단위, 함수 단위 또는 임의의 코드 조각 등 다양하게 처리 가능.
- 변환 시점: 해당 코드가 실행 직전에 변환되며, 이후 캐싱 (caching) 을 통해 재사용 가능합니다. 따라서 동일한 코드를 반복적으로 사용할 때 다시 컴파일할 필요가 없습니다.
A.3) 장점
JIT 컴파일은 인터프리터 (interpreter) 에 비해 성능이 훨씬 뛰어나며, 경우에 따라 정적 (static) 컴파일보다도 더 나은 성능을 제공합니다. 이는 런타임 환경에서만 가능한 최적화 덕분입니다.
A.3.1) 주요 장점
-
CPU 및 운영 체제에 맞춘 최적화
- 예를 들어, CPU 가 SSE2 벡터 명령어를 지원하는 경우 이를 감지하여 해당 명령어를 선택적으로 활용할 수 있습니다.
-
실행 환경 기반 최적화
- 시스템은 실제 프로그램 실행 데이터를 수집하고 이를 기반으로 재배열 및 재컴파일하여 성능을 극대화합니다.
- 참고로 일부 정적 컴파일러도 프로필 정보를 입력받아 최적화를 수행할 수 있지만, JIT 방식에서는 실시간으로 이루어진다는 점이 차별화됩니다.
-
글로벌 코드 최적화
- 예: 라이브러리 함수의 인라이닝(inlining).
- 동적 링크 (dynamic linking) 의 장점을 유지하면서도 정적 링크 (static linking) 의 오버헤드를 피할 수 있습니다.
-
캐시 활용 효율성 향상
- 특히 가비지 컬렉션 (Garbage Collection) 을 사용하는 언어에서는 실행된 코드를 더 쉽게 재배열하여 캐시 활용도를 높일 수 있습니다.