Zend OPcache: pojęcie, instalacja i konfiguracja, wartości php.ini oraz wyłączanie JIT

Środowisko testowe Rodzina RHELAlmaLinux 9.8konto rootSprawdzono 2026-10-16

Zend OPcache to rozszerzenie PHP, które kompiluje skrypty PHP do bytecode i zapisuje go w pamięci współdzielonej, dzięki czemu przy ponownym uruchomieniu tego samego pliku kompilacja jest pomijana. Gdy po włączeniu JIT na serwerze WordPress z PHP 8.3 na wszystkich stronach pojawił się błąd 500, serwer przywrócono do działania, zostawiając OPcache bez zmian i wyłączając tylko JIT.

Od PHP 5.5 OPcache jest domyślnie dołączony do PHP.

1️⃣ Pojęcie Zend OPcache: cache bytecode

Przy każdym żądaniu skrypt PHP przechodzi trzy etapy: odczyt pliku, kompilację do bytecode i wykonanie. Gdy OPcache działa, od drugiego żądania dla tego samego pliku pierwsze dwa etapy znikają i zostaje samo wykonanie.

Pamięć współdzielona, w której OPcache zapisuje bytecode, jest używana wspólnie przez wszystkie workery PHP-FPM. Jeśli do tego samego PHP-FPM podłączonych jest kilka witryn, skrypty tych witryn też trafiają do jednej pamięci współdzielonej.

🧩 Obsługa żądań bez OPcache i z OPcache
Diagram objaśniający
🧠 OPcache
📨 Żądanie
🧰 PHP-FPM Workery
Worker 1Pierwsze żądanie
Worker 2Drugie żądanie
Worker 3czekanie
Trzy etapy przy każdym żądaniuPierwsze żądanie · trzy etapyTylko wykonanie→
⚙️ Przetwarzanie skryptu PHP
Odczyt plikuPominięte
→
Kompilacja do bytecodePominięte
→
UruchomWykonanie PHP · zapytanie do bazy danych
Pamięć współdzielona nieużywana↓ Bytecode zapisany↑ Użyty bytecode z pamięci współdzielonej
🧠 Pamięć współdzielona
Bytecode (skompilowany kod PHP)
Używana wspólnie przez wszystkie workery PHP-FPM · jedna pamięć współdzielona nawet przy kilku witrynach
Bez OPcache skrypt PHP przechodzi przy każdym żądaniu trzy etapy: odczyt pliku, kompilację do bytecode i wykonanie.
Bez OPcache drugie żądanie dla tego samego pliku też ponownie przechodzi trzy etapy: odczyt pliku, kompilację do bytecode i wykonanie.
Gdy OPcache działa, pierwsze żądanie przechodzi trzy etapy, a potem zapisuje bytecode w pamięci współdzielonej.
Od drugiego żądania dla tego samego pliku pierwsze dwa etapy znikają i zostaje samo wykonanie; pamięć współdzielona jest używana wspólnie przez wszystkie workery PHP-FPM.

OPcache zapisuje skompilowany kod PHP, więc przy każdym otwarciu strony nadal odbywa się wykonanie PHP i zapytania do bazy danych. Całkowite pominięcie wykonania PHP przez zapisanie gotowego HTML to zadanie cache stron.

2️⃣ Sprawdzanie instalacji PHP OPcache

To, czy OPcache jest zainstalowany, sprawdzisz w ostatniej linii wyniku polecenia [php -v].

php -v
PHP 8.3.22 (cli) (built: Jun  3 2025 17:17:57) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.3.22, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.22, Copyright (c), by Zend Technologies

Jeśli brakuje ostatniej linii, zainstaluj go przez dnf. Pakiet zwykle nazywa się php-opcache; jeśli z repozytorium Remi zainstalowano obok siebie kilka wersji PHP, do nazwy dochodzi numer wersji, jak w php83-php-opcache.

dnf -y install php-opcache

Pakiet php-opcache z repozytorium Remi ładuje rozszerzenie linią [zend_extension=opcache] w pliku [/etc/php.d/10-opcache.ini]. Po instalacji uruchom PHP-FPM ponownie, aby OPcache obejmował też żądania webowe.

3️⃣ Konfiguracja OPcache: wartości php.ini

Ustawienia OPcache mogą znajdować się w dwóch miejscach: w sekcji [opcache] pliku [/etc/php.ini] oraz w [/etc/php.d/10-opcache.ini].

php --ini
Configuration File (php.ini) Path: /etc
Loaded Configuration File:         /etc/php.ini
Scan for additional .ini files in: /etc/php.d
Additional .ini files parsed:      /etc/php.d/10-opcache.ini,

Pliki z folderu php.d są czytane po php.ini, więc jeśli ta sama pozycja jest wpisana w obu miejscach, obowiązuje wartość z php.d.

Poniższa tabela pokazuje domyślne wartości PHP 8.3 oraz wartości zastosowane na sprawdzanym serwerze WordPress.

PozycjaWartość domyślna w PHP 8.3Zastosowana wartośćZnaczenie
opcache.enable11Włącza OPcache
opcache.enable_cli01Używane też w PHP z wiersza poleceń (wp-cli itp.)
opcache.memory_consumption1281024Pamięć współdzielona, w której zapisywany jest bytecode (MB)
opcache.interned_strings_buffer816Pamięć zapisująca te same ciągi znaków tylko raz (MB)
opcache.max_accelerated_files1000010000Górny limit liczby kluczy, które można zapisać w cache (rzeczywisty limit to liczba pierwsza równa tej wartości lub większa: 16229 dla 10000)
opcache.max_wasted_percentage510Jeśli brakuje pamięci, a zmarnowane miejsce przekracza ten odsetek, cache jest czyszczony i uruchamiany od nowa
opcache.validate_timestamps11Sprawdza, czy pliki się zmieniły
opcache.revalidate_freq260Co ile sprawdzane są zmiany plików (sekundy)
opcache.jittracingdisableTryb JIT (od PHP 8.4 wartością domyślną jest disable)
opcache.jit_buffer_size00Pamięć JIT; przy 0 JIT nie działa (od PHP 8.4 wartością domyślną jest 64M)

Wartości wpisane w sekcji [opcache] pliku [/etc/php.ini] podano poniżej. Rozmiar pamięci dobiera się do pamięci serwera, a [opcache.max_accelerated_files] do liczby plików WordPressa.

[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=1024
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=10
opcache.validate_timestamps=1
opcache.revalidate_freq=60

Jeśli w php.ini ponownie wpiszesz linię [zend_extension], rozszerzenie zostanie załadowane dwa razy i pojawi się ostrzeżenie [Cannot load Zend OPcache].

Przy [opcache.revalidate_freq] równym 60 po edycji pliku PHP stary kod może działać jeszcze do 60 sekund.

Na serwerze WordPress, na którym pliki PHP zmieniają się często, zostaw [opcache.validate_timestamps] na 1, aby zmiany plików były sprawdzane. Wartość 0, którą dokumentacja Symfony zaleca dla serwerów produkcyjnych, pasuje do serwerów, na których pliki PHP zmieniają się tylko przy wdrożeniu nowej wersji.

Nawet przy [opcache.validate_timestamps] równym 0 WordPress sam czyści cache zmienionych plików, gdy aktualizujesz z panelu administracyjnego. Jeśli jednak aktualizujesz przez wp-cli albo edytujesz pliki przez SSH, stary kod działa do ponownego uruchomienia PHP-FPM.

4️⃣ Wyłączanie JIT w OPcache

JIT w PHP 8 przyspiesza zadania obciążające procesor, więc w aplikacji takiej jak WordPress, która obsługuje żądania webowe, jego efekt jest niewielki. Również w pomiarze WordPressa opublikowanym w PHP JIT RFC przebieg z włączonym JIT obsłużył 326 żądań na sekundę, a z wyłączonym 315.

Na serwerze WordPress z PHP 8.3.22 włączono JIT ustawieniami [opcache.jit=tracing] i [opcache.jit_buffer_size=128M]. Trzy dni później, w dniu, w którym nawał żądań kilkakrotnie zrestartował workery PHP-FPM, na wszystkich stronach wystąpił błąd 500.

W logu błędów pozostał komunikat [Allowed memory size of 1073741824 bytes exhausted]. Następujące po nim [tried to allocate 4295229440 bytes] to zapis próby jednorazowego przydzielenia 4 GB przy limicie pamięci PHP wynoszącym 1 GB. Po wyłączeniu JIT te same żądania były obsługiwane normalnie.

JIT wyłącza się, wpisując poniższe dwie linie w [/etc/php.d/10-opcache.ini]. Nawet jeśli w [/etc/php.ini] zostały ustawienia JIT, obowiązują wartości z tego pliku.

opcache.jit=disable
opcache.jit_buffer_size=0

W PHP 8.3 wartością domyślną [opcache.jit_buffer_size] jest 0, więc bez osobnego ustawienia JIT nie działa. Od PHP 8.4 wartością domyślną [opcache.jit] też jest disable.

5️⃣ Zastosowanie i sprawdzenie ustawień

Zmienione ustawienia zaczynają obowiązywać dopiero po ponownym uruchomieniu PHP-FPM.

systemctl restart php-fpm

Po ponownym uruchomieniu pamięć współdzielona OPcache jest opróżniana i przydzielana od nowa z nowymi ustawieniami.

php -i | grep -E '^opcache\.(enable|memory_consumption|revalidate_freq|validate_timestamps|jit) '
opcache.enable => On => On
opcache.jit => disable => disable
opcache.memory_consumption => 1024 => 1024
opcache.revalidate_freq => 60 => 60
opcache.validate_timestamps => On => On

Wartości wypisywane przez [php -i] to ustawienia PHP z wiersza poleceń. W rodzinie RHEL PHP-FPM czyta te same pliki [/etc/php.ini] i [/etc/php.d], więc wartości są takie same.

Jeśli wywołasz [opcache_get_status()] w wierszu poleceń, liczba skryptów w cache wyniesie 0. PHP z wiersza poleceń przy każdym uruchomieniu tworzy nową pamięć współdzieloną, więc użycie PHP-FPM sprawdza się, umieszczając poniższy plik w folderze dokumentów webowych i otwierając go w przeglądarce.

<?php
header('Content-Type: text/plain');
$s = opcache_get_status(false);
print_r($s['memory_usage']);
print_r($s['opcache_statistics']);
print_r($s['interned_strings_usage']);
var_dump($s['cache_full']);

Jeśli [cache_full] ma wartość true, pamięć współdzielona albo klucze są zapełnione. Po sprawdzeniu od razu usuń ten plik.

Na serwerze, na którym trzy witryny WordPress używają tego samego PHP-FPM, z 1024 MB pamięci współdzielonej zajęte było 317 MB. W cache było od 3 366 do 4 222 skryptów na witrynę, łącznie 11 358.

OPcache zapisuje skrypty pod ich rzeczywistą ścieżką, a dla plików ładowanych ścieżką względną tworzy jeszcze jeden klucz z dołączonym katalogiem roboczym, więc kluczy jest więcej niż skryptów. Przy 11 358 skryptach klucze wypełniły limit 16 229, a bufor ciągów znaków o wielkości 16 MB też nie miał już wolnego miejsca.

Gdy klucze są zapełnione, nowe skrypty nie trafiają do cache i są kompilowane przy każdym żądaniu. W ciągu 5 minut i 21 sekund liczba chybień cache wzrosła z 18 408 do 36 027, ale liczba skryptów w cache pozostała równa 11 358.

Na serwerze z wieloma instalacjami WordPressa albo z dużą liczbą wtyczek ustaw [opcache.max_accelerated_files] z zapasem, aby limit kluczy się nie zapełnił. Przy 20000 rzeczywisty limit kluczy wynosi 32 531. Jeśli bufor ciągów znaków jest pełny, zwiększ też [opcache.interned_strings_buffer].

🔢 FAQ & polecane treści

To ustawienie usunięto w PHP 7.2, więc w PHP 8 nie wpływa na działanie, nawet jeśli zostało w php.ini. Na serwerze, który przeniósł stare ustawienia, możesz tę linię usunąć.

OPcache zapisuje skompilowany kod PHP, a cache obiektów Redis zapisuje wyniki zapytań do bazy danych. Ponieważ zapisują różne rzeczy, można ich używać razem.

Na serwerze, który uruchamia PHP przez PHP-FPM, OPcache działa wewnątrz PHP-FPM, więc ponownie uruchamia się tylko PHP-FPM. Na serwerze, który uruchamia PHP jako moduł Apache (mod_php), uruchom ponownie Apache.

ℹ️ Informacja o linkach partnerskich
Treści tej witryny zawierają linki partnerskie. Jeśli odwiedzający kupi produkt lub usługę przez taki link, witryna otrzymuje od sprzedawcy prowizję. Kwota płacona przy tym przez kupującego (podczas promocji spada↓) nie wzrasta. Podane ceny, rabaty i dostępność odnoszą się do chwili pisania i mogą różnić się od stanu faktycznego, dlatego przed zakupem sprawdź je u sprzedawcy. Produkty wybieramy i oceniamy według własnych kryteriów, a prowizja nie wpływa ani na kolejność prezentacji, ani na treść ocen.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *

Prove your humanity: 6   +   1   =