0Pricing
PHP Academy · 강의

OPcache와 JIT 컴파일

바이트코드 캐싱과 JIT로 PHP의 속도를 높입니다.

OPcache와 JIT 컴파일은(는) CoddyKit의 무료 PHP Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 PHP Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

컴파일 결과 캐싱

OPcache는 컴파일된 연산 코드를 공유 메모리에 저장하므로 PHP는 모든 요청마다 어휘 분석, 구문 분석, 컴파일을 반복하지 않습니다. 여기에 더해 JIT(PHP 8.0부터)는 자주 실행되는 연산 코드를 네이티브 기계어로 컴파일합니다. 두 기능은 함께 PHP 성능의 기반을 이룹니다.

이 단원에서는 OPcache 설정, 프리로딩, JIT 조정을 다룹니다.

OPcache의 기능

각 파일의 컴파일된 op_array는 모든 FPM 작업자가 사용하는 공유 메모리 영역에 캐시됩니다. 캐시를 찾은 요청은 연산 코드를 직접 재사용합니다. OPcache는 파일을 처음 컴파일할 때 최적화(상수 접기, 도달할 수 없는 코드 제거, 연산 코드 융합)도 수행합니다.

; Core OPcache config (php.ini)
opcache.enable = 1
opcache.memory_consumption = 256      ; MB of shared memory
opcache.interned_strings_buffer = 16  ; MB for interned strings
opcache.max_accelerated_files = 20000 ; cap on cached scripts

타임스탬프 검증

validate_timestamps는 OPcache가 파일의 수정 시간을 다시 확인할지 결정합니다. 개발 환경에서는 이 옵션을 켜고 revalidate_freq를 짧게 설정하십시오. 운영 환경에서는 0으로 설정하여 PHP가 파일 상태를 확인하지 않게 하고, 캐시를 비우거나 이미지를 다시 빌드하여 배포하십시오.

; Production: never re-stat files
opcache.validate_timestamps = 0

; Development: check every 2 seconds
; opcache.validate_timestamps = 1
; opcache.revalidate_freq = 2

캐시 검사

opcache_get_status()는 적중률, 메모리 사용량, 캐시된 스크립트를 보고하고, opcache_get_configuration()은 설정을 보여 줍니다. 적중률이 낮거나 재시작이 잦다면 메모리가 너무 적거나 파일이 너무 많은 것입니다.

<?php
if (function_exists('opcache_get_status')) {
    $s = opcache_get_status(false);
    if ($s) {
        printf("hits:   %d\n", $s['opcache_statistics']['hits']);
        printf("misses: %d\n", $s['opcache_statistics']['misses']);
        printf("hit %%: %.2f\n", $s['opcache_statistics']['opcache_hit_rate']);
        printf("used:   %.1f MB\n", $s['memory_usage']['used_memory'] / 1048576);
    } else {
        echo "OPcache enabled but no status (likely CLI)\n";
    }
} else {
    echo "OPcache not available\n";
}
?>

프리로딩

프리로딩(PHP 7.4 이상)은 서버가 시작될 때 클래스와 함수 집합을 한 번 컴파일하고 이를 메모리에 영구적으로 유지합니다. 따라서 자동 로딩이나 요청마다 연결하는 과정 없이 모든 요청에서 사용할 수 있습니다. opcache.preload이 미리 준비할 파일을 불러오는 스크립트를 가리키도록 설정하십시오.

; php.ini
opcache.preload = /app/preload.php
opcache.preload_user = www-data

프리로드 스크립트 작성

프리로드 스크립트는 마스터 프로세스에서 실행됩니다. 클래스를 실행하지 않고 불러오려면 opcache_compile_file()을 사용하거나 단순히 require하십시오. 프레임워크는 프리로드 목록을 생성합니다. 다음은 그 형태의 예입니다.

<?php
// preload.php — runs once at startup
$dir = '/app/src';
$rii = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($dir)
);

foreach ($rii as $file) {
    if ($file->getExtension() === 'php') {
        // Compiles + links the class into shared memory
        opcache_compile_file($file->getPathname());
    }
}
?>

JIT 도입

연산 코드가 캐시되어 있어도 VM은 여전히 이를 해석합니다. JIT는 자주 실행되는 연산 코드 시퀀스를 네이티브 CPU 명령어로 컴파일하여 VM 디스패치 오버헤드를 제거합니다. CPU를 집중적으로 사용하는 숫자 계산 코드에서는 이득이 크지만, 일반적인 입출력 중심 웹 앱에서는 데이터베이스와 네트워크에서 시간을 보내므로 이득이 작습니다.

JIT 설정

JIT는 OPcache 내부에서 작동하므로 OPcache가 켜져 있어야 합니다. opcache.jit_buffer_size는 생성된 기계어를 저장할 공간을 할당하며(0이면 JIT가 비활성화됨), opcache.jit는 실행 조건과 최적화 전략을 제어하는 네 자리 모드입니다.

; Enable JIT (requires opcache.enable=1)
opcache.jit_buffer_size = 128M
opcache.jit = tracing        ; alias for 1254, the common default

; The 4 digits CRTO mean:
;   C - CPU optimization flags
;   R - register allocation
;   T - trigger (when to JIT)
;   O - optimization level

추적형 JIT와 함수 JIT

두 가지 전략이 있습니다. 함수 JIT(모드 1205)는 처음 호출할 때 함수 전체를 컴파일합니다. 추적형 JIT(1254, 기본 tracing 별칭)는 실행을 분석한 뒤 자주 실행되는 루프와 경로를 컴파일합니다. 관찰된 형식에 맞게 특화하므로 더 나은 결과를 내는 경우가 많습니다. 추적형 JIT를 기본값으로 사용하는 것이 권장됩니다.

; Tracing JIT (recommended) — compiles hot traces
opcache.jit = tracing

; Function JIT — compiles entire functions when first called
; opcache.jit = function

; Disable JIT but keep opcode cache
; opcache.jit_buffer_size = 0

JIT 효과 측정

JIT는 짧고 반복적인 숫자 계산 루프에서 특히 효과적입니다. 이 독립 실행형 벤치마크(만델브로트와 비슷한 내부 루프)는 JIT가 실행 시간을 크게 줄일 수 있는 CPU 중심 작업의 예입니다. jit_buffer_size를 켠 경우와 끈 경우에 실행하여 비교하십시오.

<?php
function mandelEscape(float $cr, float $ci, int $max): int {
    $zr = 0.0; $zi = 0.0; $n = 0;
    while ($n < $max && ($zr * $zr + $zi * $zi) <= 4.0) {
        $t  = $zr * $zr - $zi * $zi + $cr;
        $zi = 2.0 * $zr * $zi + $ci;
        $zr = $t;
        $n++;
    }
    return $n;
}

$start = hrtime(true);
$sum = 0;
for ($y = 0; $y < 200; $y++) {
    for ($x = 0; $x < 200; $x++) {
        $sum += mandelEscape($x / 100 - 2, $y / 100 - 1, 256);
    }
}
printf("sum=%d  time=%.2f ms\n", $sum, (hrtime(true) - $start) / 1e6);
?>

이득을 기대하지 말아야 할 때(NOT)

일반적인 요청은 데이터베이스를 조회하고, 템플릿을 렌더링하고, JSON을 반환하므로 CPU가 원시 산술 연산을 많이 수행하지 않습니다. 따라서 JIT의 이득이 한 자릿수 퍼센트에 그치거나 전혀 없을 수 있습니다. 먼저 OPcache, 프리로딩, 적절한 데이터베이스 및 캐시 사용을 우선하십시오. 이미지 처리, 수학 계산, 구문 분석기와 같은 계산 집약적 코드에만 JIT 조정을 적용하십시오.

빠른 확인

일반적인 OPcache 캐싱으로는 얻을 수 없지만 프리로딩으로 얻을 수 있는 것은 무엇인가요?

복습

OPcache는 컴파일된 연산 코드 배열을 공유 메모리에 캐시하고 최적화를 수행합니다. 운영 환경에서는 validate_timestamps=0으로 설정하고 memory_consumption/max_accelerated_files를 적절히 지정하십시오. 프리로딩은 선택한 클래스를 시작 시 메모리에 상주하게 합니다. JIT(OPcache 내부에서 작동하며 jit_buffer_size가 필요함)는 자주 실행되는 코드를 네이티브 명령어로 컴파일합니다. CPU 중심 수학 계산에서는 큰 이득이 있지만 입출력 중심 웹 앱에서는 이득이 작습니다. opcache_get_status()로 상태를 확인하십시오.

자주 묻는 질문

“OPcache와 JIT 컴파일” 강의는 무료인가요?

네 — “OPcache와 JIT 컴파일” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 PHP Academy 강의 전체를 잠금 해제할 수 있습니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“OPcache와 JIT 컴파일”에서 뭘 배우나요?

바이트코드 캐싱과 JIT로 PHP의 속도를 높입니다. 브라우저에서 직접 실행하는 실습 코드로 PHP Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

PHP Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 PHP Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“OPcache와 JIT 컴파일” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 PHP Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 PHP Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Zend Engine의 작동 원리
  2. 메모리 관리와 가비지 컬렉션
  3. OPcache와 JIT 컴파일
  4. C로 기본 PHP 확장 기능 작성
← PHP Academy(으)로 돌아가기