0Pricing
PHP Academy · Lekcja

OPcache i kompilacja JIT

Przyspiesz PHP dzięki buforowaniu bytecode’u i JIT

OPcache i kompilacja JIT to bezpłatna lekcja PHP Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej PHP Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs PHP Academy zawiera 4 lekcji w sumie.

Buforowanie kompilacji

OPcache przechowuje skompilowane kody operacyjne w pamięci współdzielonej, dzięki czemu PHP pomija analizę leksykalną, analizę składniową i kompilację przy każdym żądaniu. Dodatkowo JIT (od PHP 8.0) kompiluje często wykonywane kody operacyjne do natywnego kodu maszynowego. Razem stanowią one fundament wydajności PHP.

W tej lekcji omówiono konfigurowanie OPcache, wstępne ładowanie oraz dostrajanie JIT.

Jak działa OPcache

Skompilowana dla każdego pliku struktura op_array jest buforowana w segmencie pamięci współdzielonej używanym przez wszystkie procesy robocze FPM. Żądanie, które trafi do bufora, korzysta bezpośrednio z ponownie użytych kodów operacyjnych. Przy pierwszej kompilacji pliku OPcache uruchamia również optymalizator (składanie stałych, eliminację martwego kodu, łączenie kodów operacyjnych).

; 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

Walidacja znaczników czasu

validate_timestamps określa, czy OPcache ponownie sprawdza czasy modyfikacji plików. W środowisku deweloperskim należy pozostawić tę opcję włączoną i ustawić krótki revalidate_freq; w produkcji należy ustawić ją na 0, aby PHP nigdy nie wykonywał stat na plikach, a wdrożenia realizować przez wyczyszczenie pamięci podręcznej (lub ponowne zbudowanie obrazu).

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

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

Inspekcja pamięci podręcznej

opcache_get_status() raportuje współczynnik trafień, zużycie pamięci i buforowane skrypty; opcache_get_configuration() pokazuje ustawienia. Niski współczynnik trafień lub częste restarty oznaczają zbyt mało pamięci albo zbyt dużą liczbę plików.

<?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";
}
?>

Wstępne ładowanie

Wstępne ładowanie (PHP 7.4+) kompiluje zestaw klas i funkcji raz podczas uruchamiania serwera i przechowuje je na stałe w pamięci. Są one dostępne dla każdego żądania bez autoloadingu ani linkowania przy każdym żądaniu. Ustawienie opcache.preload należy skierować na skrypt, który załaduje wymagane pliki i rozgrzeje pamięć podręczną.

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

Pisanie skryptu wstępnego ładowania

Skrypt wstępnego ładowania działa w procesie głównym. Należy użyć opcache_compile_file(), aby załadować klasy bez ich wykonywania, albo po prostu użyć konstrukcji require. Frameworki generują listę wstępnego ładowania; oto jej struktura.

<?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 wkracza do akcji

Nawet przy buforowanych kodach operacyjnych maszyna wirtualna nadal je interpretuje. JIT kompiluje często wykonywane sekwencje kodów operacyjnych do natywnych instrukcji procesora, usuwając narzut rozsyłania w maszynie wirtualnej. Zysk jest duży w przypadku obliczeniowego kodu numerycznego, ale umiarkowany w typowych aplikacjach internetowych zależnych od operacji wejścia-wyjścia (które spędzają czas na komunikacji z bazą danych i siecią, a nie na pracy procesora).

Konfigurowanie JIT

JIT działa wewnątrz OPcache, dlatego OPcache musi być włączony. opcache.jit_buffer_size przydziela miejsce na wygenerowany kod maszynowy (wartość 0 wyłącza JIT). opcache.jit to czterocyfrowy tryb sterujący wyzwalaniem i strategią optymalizacji.

; 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 śledzący a JIT funkcyjny

Istnieją dwie strategie: JIT funkcyjny (tryb 1205) kompiluje całe funkcje przy pierwszym wywołaniu, natomiast JIT śledzący (1254, domyślny alias tracing) profiluje wykonanie i kompiluje często wykonywane pętle oraz ścieżki. Często daje to lepsze wyniki, ponieważ specjalizuje kod na podstawie zaobserwowanych typów. JIT śledzący jest zalecanym ustawieniem domyślnym.

; 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

Pomiar wpływu JIT

JIT najlepiej sprawdza się w ciasnych pętlach numerycznych. Ten samodzielny test porównawczy (wewnętrzna pętla w stylu Mandelbrota) reprezentuje obciążenie obliczeniowe, przy którym JIT może znacznie skrócić czas wykonywania. Należy uruchomić go z ustawionym jit_buffer_size i bez niego, aby porównać wyniki.

<?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);
?>

Kiedy NIE oczekiwać wzrostu wydajności

W typowym żądaniu, które wykonuje zapytanie do bazy danych, renderuje szablon i zwraca JSON, procesor wykonuje niewiele surowych obliczeń arytmetycznych — JIT może dać kilkuprocentowy wzrost wydajności albo nie dać go wcale. Najpierw należy zadbać o OPcache, wstępne ładowanie oraz właściwe wykorzystanie bazy danych i pamięci podręcznej. Dostrajanie JIT warto pozostawić do przetwarzania obrazów, obliczeń matematycznych, parserów i innego kodu wymagającego intensywnych obliczeń.

Szybki test

Co daje wstępne ładowanie, czego nie daje zwykłe buforowanie OPcache?

Podsumowanie

OPcache buforuje skompilowane op_arrays w pamięci współdzielonej i uruchamia optymalizator; w środowisku produkcyjnym należy ustawić validate_timestamps=0 oraz odpowiednio dobrać wartości memory_consumption/max_accelerated_files. Wstępne ładowanie utrzymuje wybrane klasy w pamięci od momentu uruchomienia. JIT (wewnątrz OPcache, wymaga jit_buffer_size) kompiluje często wykonywany kod do natywnych instrukcji — daje duże korzyści w obliczeniach zależnych od procesora, ale niewielkie w aplikacjach internetowych zależnych od operacji wejścia-wyjścia. Do weryfikacji należy użyć opcache_get_status().

Często zadawane pytania

Czy lekcja „OPcache i kompilacja JIT” jest bezpłatna?

Tak — pełny tekst „OPcache i kompilacja JIT” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu PHP Academy, przejdź na CoddyKit PRO. Kurs PHP Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „OPcache i kompilacja JIT”?

Przyspiesz PHP dzięki buforowaniu bytecode’u i JIT Ćwiczysz PHP Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć PHP Academy?

Nie wymagamy żadnego doświadczenia. PHP Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „OPcache i kompilacja JIT”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji PHP Academy?

Tak. Każda lekcja PHP Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Jak działa Zend Engine
  2. Zarządzanie pamięcią i garbage collection
  3. OPcache i kompilacja JIT
  4. Pisanie podstawowego rozszerzenia PHP w C
← Powrót do PHP Academy