Krótko: PHP JIT (kompilator just-in-time) tłumaczy często wykonywany kod PHP w czasie działania na kod maszynowy. Pojawił się w PHP 8.0, jest częścią OPcache i od PHP 8.4 jest domyślnie wyłączony. Zadania wymagające dużej mocy obliczeniowej stają się dzięki niemu wyraźnie szybsze, typowe strony, takie jak WordPress, prawie wcale. Większy zysk dają OPcache, aktualna wersja PHP i odpowiednio ustawione zarządzanie procesami, a każda aktualna wersja przynosi jednocześnie potrzebne poprawki bezpieczeństwa.
Czym jest kompilator JIT w PHP?
PHP jest językiem interpretowanym: kod źródłowy jest najpierw tłumaczony na bajtkod, czyli tzw. opcody, a te wykonuje Zend Engine. JIT idzie o krok dalej. Obserwuje, które fragmenty kodu wykonują się często, i tłumaczy właśnie je na kod maszynowy dla procesora. Od tej chwili działają bez objazdu przez interpreter.
RFC wprowadzające opisuje JIT jako niemal samodzielną część OPcache. Wytworzony kod maszynowy leży w dodatkowym obszarze wspólnej pamięci OPcache. W PHP 8.4 projekt zbudował JIT od nowa; według strony wydania nowa implementacja opiera się na frameworku IR, wspólnej reprezentacji pośredniej do generowania kodu. Jak działa silnik pod spodem, wyjaśnia Zend Engine.
Najpierw OPcache: właściwa podstawa wydajności
Bez OPcache PHP tłumaczy każdy plik od nowa przy każdym żądaniu. OPcache przechowuje bajtkod we wspólnej pamięci, dzięki czemu wszystkie workery używają go ponownie. Dla strony z systemem zarządzania treścią jest to zdecydowanie najważniejsza dźwignia. Od PHP 8.5 OPcache jest według przyjętego RFC na stałe skompilowany w PHP; znane ustawienia ini nadal sterują tym, czy pamięć podręczna jest aktywna.
Ważne wartości domyślne według podręcznika: opcache.enable=1, opcache.enable_cli=0, opcache.validate_timestamps=1 i opcache.revalidate_freq=2. Przy ostatnim ustawieniu OPcache sprawdza co najwyżej co dwie sekundy, czy pliki się zmieniły. Kto wyłączy validate_timestamps, musi po każdym wdrożeniu opróżnić pamięć podręczną albo zrestartować PHP. Więcej w artykule OPcache wyjaśniony.
Konfiguracja PHP JIT: tryby i ustawienia
JIT jest sterowany dwiema dyrektywami:
| Dyrektywa | Domyślnie od 8.4 | Domyślnie przed 8.4 | Znaczenie |
|---|---|---|---|
opcache.jit |
disable |
tracing |
tryb JIT |
opcache.jit_buffer_size |
64M |
0 |
pamięć na wytworzony kod maszynowy, 0 wyłącza JIT |
Dla opcache.jit podręcznik zna te wartości: disable (całkowicie wyłączony, w czasie działania nie do włączenia), off (wyłączony, ale w czasie działania do włączenia), tracing lub on (zalecany dla większości użytkowników) oraz function. Obok tego istnieje czterocyfrowy zapis liczbowy do dokładnych ustawień.
; włączać JIT celowo, np. dla workerów wymagających dużej mocy obliczeniowej
opcache.enable=1
opcache.jit=tracing
opcache.jit_buffer_size=64M
Czy JIT działa, pokazuje status OPcache:
php -i | grep -i "opcache.jit" # ustawienia CLI
php --ri "Zend OPcache" # konfiguracja rozszerzenia OPcache
Proszę pamiętać, że wiersz poleceń może używać innych ustawień niż PHP-FPM. Dla pracy webowej liczy się wynik phpinfo() w kontekście FPM, najlepiej wywołany tylko wewnętrznie i potem usunięty.
Co JIT daje w praktyce?
Autorzy RFC mierzyli: syntetyczny skrypt bench.php działał z JIT ponad dwa razy szybciej. W rzeczywistych aplikacjach zysk był niewielki; WordPress osiągnął 326 zamiast 315 żądań na sekundę, a parser PHP działał około 1,3 raza szybciej. RFC mówi otwarcie, że JIT nie przyspiesza wyraźnie rzeczywistych aplikacji, takich jak WordPress.
Przyczyna leży w profilu typowych aplikacji webowych. Większość czasu czekają one na bazę danych, system plików lub usługi zewnętrzne. Szybsza ścieżka procesora niewiele tam pomaga. Skorzystać mogą natomiast przetwarzanie obrazów w PHP, obliczenia matematyczne, parsery lub długo działające workery.
Wydajność bez JIT: skuteczniejsze dźwignie
Dla stron firmowych i sklepów opłaca się taka kolejność:
- Aktualna wersja PHP: Nowe wersje przynoszą optymalizacje, a przede wszystkim poprawki bezpieczeństwa.
- Prawidłowe wymiarowanie OPcache: dość pamięci i miejsca na wszystkie pliki aplikacji.
- Odpowiednie ustawienie PHP-FPM:
pm.max_childrendopasować do dostępnej pamięci RAM, zamiast ślepo zwiększać. - Sprawdzenie bazy danych: znaleźć wolne zapytania, ustawić indeksy.
- Cache na poziomie aplikacji: cache stron lub obiektów, tam gdzie system to obsługuje.
- Mierzyć zamiast zgadywać:
request_slowlog_timeoutw PHP-FPM zapisuje dla wolnych żądań backtrace w slowlogu.
JIT, wydajność i bezpieczeństwo
Wydajność i bezpieczeństwo są ze sobą powiązane ściślej, niż się wydaje. Po pierwsze: każdy dodatkowy komponent to dodatkowy kod. RFC wprowadzające samo wymienia ryzyko błędów w JIT, w generowaniu kodu i przydziale rejestrów, a także trudniejsze szukanie usterek. Kto nie potrzebuje JIT w sposób mierzalny, zostawia go przy wartości domyślnej disable.
Po drugie: OPcache i workery trzymają kod w pamięci. Po aktualizacji bezpieczeństwa, takiej jak ta dotycząca PHP2Shell, stare procesy działają dalej ze starym kodem, dopóki nie zostaną zrestartowane. Samo opróżnienie pamięci podręcznej nie zastępuje tego restartu, ponieważ luki CVE-2026-109618 i CVE-2026-109619 tkwią w samej binarce PHP.
Po trzecie: największy zysk wydajności, czyli aktualna wersja, jest jednocześnie najważniejszym środkiem ochrony. PHP 8.2 kończy wsparcie 31.12.2026; kto przejdzie teraz na 8.4 lub 8.5, zyskuje jedno i drugie. Jak utrzymujemy systemy trwale szybkie i utwardzone, opisuje utwardzanie serwerów WWW z PHP.
Jak konkretnie pomaga PHP SOS?
- Analiza stanu obecnego: Odczytujemy ustawienia OPcache, JIT i FPM i porównujemy je z obciążeniem i pamięcią RAM.
- Pomiar wąskich gardeł: Za pomocą slowloga i wskaźników serwera ustalamy, gdzie faktycznie ucieka czas.
- Bezpieczna konfiguracja: JIT tylko tam, gdzie wykazanie pomaga; OPcache tak, aby wdrożenia i aktualizacje działały czysto.
- Planowanie aktualizacji: Zmiany wersji z testem i udokumentowanym restartem, aby tempo i stan poprawek się zgadzały.
Częste pytania
Czy JIT w PHP jest domyślnie aktywny?
Od PHP 8.4 już nie: domyślną wartością opcache.jit jest disable. Wcześniej domyślnie było tracing, ale bufor opcache.jit_buffer_size miał wartość 0, przez co JIT również nie działał.
Czy JIT przyspiesza WordPressa?
Prawie wcale. Już w RFC wprowadzającym autorzy piszą, że JIT nie przyspiesza wyraźnie rzeczywistych aplikacji, takich jak WordPress. Ich wynik pomiaru wzrósł z 315 do 326 żądań na sekundę.
Czy potrzebuję OPcache, jeśli nie używam JIT?
Tak. OPcache przechowuje przetłumaczony bajtkod we wspólnej pamięci i oszczędza ponownej kompilacji przy każdym żądaniu. To dla niemal każdej strony PHP najważniejsza dźwignia wydajności. Od PHP 8.5 OPcache jest na stałe wbudowany w PHP.
Czy JIT jest ryzykiem dla bezpieczeństwa?
Więcej kodu oznacza więcej możliwych błędów. RFC wprowadzające samo wymienia ryzyko błędów w JIT i trudniejsze szukanie usterek. Kto go nie potrzebuje, niech zostawi go wyłączonym; kto go używa, powinien szczególnie szybko instalować aktualizacje.