OPcache i JIT
OPcache działa z OxPHP od razu po instalacji. Wszystkie wątki worker PHP współdzielą jeden segment pamięci OPcache. Skrypty są kompilowane raz przy pierwszym wykonaniu, a następnie serwowane z cache'u przez każdy worker. Włączenie tego współdzielenia nie wymaga żadnej dodatkowej konfiguracji.
Jak OPcache współpracuje z OxPHP
OxPHP rejestruje się jako nazwany SAPI, a OPcache traktuje go identycznie jak inne serwerowe SAPI. Kluczowe cechy to:
- Współdzielony cache między workerami: wszystkie wątki worker PHP korzystają z tego samego cache'u skompilowanych opcode'ów. Jeden worker kompiluje plik, a korzystają na tym wszystkie workery.
- Brak kompilacji per żądanie: po pierwszym żądaniu dla danego skryptu kolejne żądania całkowicie pomijają krok parsowania i kompilacji.
opcache.enable_clinie ma wpływu na OxPHP. To ustawienie dotyczy wyłącznie SAPI o nazwachcliorazphpdbg. OxPHP rejestruje się pod nazwą SAPIcli-server, więc OPcache jest sterowany wyłącznie przezopcache.enable. Ustawienieopcache.enable_clijest przydatne, jeśli w tym samym kontenerze uruchamiasz PHP CLI (np. do migracji lub poleceń Artisan). Oficjalny obraz OxPHP dostarcza PHP CLI obok binarki serwera, więc możesz ustawićopcache.enable_cli=1, jeśli Twoje skrypty CLI zyskują na cache'owaniu.
Aby włączyć OPcache, wystarczy co najmniej:
[opcache]
opcache.enable=1Oficjalny obraz Docker OxPHP bazuje na php:*-zts-alpine, który kompiluje OPcache statycznie do binarki PHP. NIE dodawaj zend_extension=opcache do swojego pliku INI. Rozszerzenie jest już załadowane, a dodanie tej linii spowoduje ostrzeżenie przy każdym starcie PHP. Potrzebna jest wyłącznie sekcja konfiguracji [opcache].
Zalecane ustawienia produkcyjne
Te ustawienia są zoptymalizowane pod produkcyjne wdrożenia kontenerowe, w których pliki PHP nie zmieniają się w czasie działania. Wyłącz walidację znaczników czasu i wykonaj preloading skompilowanych plików przy starcie, aby uzyskać maksymalną przepustowość.
[opcache]
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.file_update_protection=0
opcache.jit_buffer_size=64M
opcache.jit=tracing| Ustawienie | Zalecana wartość | Opis |
|---|---|---|
memory_consumption |
128 |
Pamięć współdzielona w MB na skompilowane skrypty. Zwiększ, jeśli opcache_get_status() pokazuje mało wolnej pamięci. |
interned_strings_buffer |
16 |
Pamięć w MB na interned strings współdzielone przez wszystkie workery. |
max_accelerated_files |
10000 |
Maksymalna liczba cache'owanych skryptów. Ustaw wyżej niż łączna liczba Twoich plików .php. |
validate_timestamps |
0 |
Gdy 0, OPcache nigdy nie sprawdza systemu plików pod kątem zmian. Aby uwzględnić zmiany w kodzie, zrestartuj kontener lub wywołaj opcache_reset(). |
revalidate_freq |
0 |
Liczba sekund między sprawdzeniami systemu plików. Nie ma efektu, gdy validate_timestamps=0. |
file_update_protection |
0 |
Liczba sekund po modyfikacji pliku, zanim plik kwalifikuje się do cache'owania. Ustaw na 0, aby cache'ować natychmiast przy starcie. |
Ustawienia deweloperskie
Na potrzeby developmentu włącz walidację znaczników czasu, aby zmiany w kodzie były uwzględniane bez restartu kontenera. Wyłącz JIT, aby uzyskać czytelniejsze ślady stosu podczas debugowania.
[opcache]
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.jit_buffer_size=0
opcache.jit=disablePrzy validate_timestamps=1 OPcache co revalidate_freq sekund sprawdza czas modyfikacji plików. Dodaje to niewielki narzut na każde żądanie, ale pozwala edytować pliki PHP i widzieć zmiany przy następnym żądaniu.
To jest zalecana strategia przeładowywania w trybie deweloperskim dla OxPHP. OPcache wykonuje sprawdzenie w linii przy każdym include, więc edycje kodu są uwzględniane przy następnym żądaniu, bez restartu kontenera i bez zewnętrznego demona nasłuchującego zmian plików. Użyj revalidate_freq=0, aby stat wykonywał się przy każdym include (najwyższa dokładność, nieco więcej operacji I/O), lub revalidate_freq=2, aby zamortyzować koszt operacji stat. Domyślna wartość pokazana powyżej to dobry kompromis, zwłaszcza gdy Twój DOCUMENT_ROOT znajduje się na wolnym bind-mount (Docker na macOS/Windows).
Czego validate_timestamps NIE przeładowuje
Kilka rodzajów zmian nadal wymaga restartu kontenera (lub recyklingu workera) nawet przy validate_timestamps=1:
- Pliki objęte preloadingiem (
opcache.preload) są linkowane do serwera przy starcie i nigdy nie są ponownie walidowane. Edytujesz plik objęty preloadingiem — restartuj kontener. - Stan bootstrapu w trybie Worker — w trybie Worker autoloader, kontener DI oraz wszelkie obiekty zbudowane w zewnętrznym zakresie żyją w pamięci workera. OPcache przekompiluje zmienione pliki klas, ale worker nie uruchomi ponownie swojego bootstrapu. W deweloperskich pętlach worker wywołaj
Worker::scheduleExit()na końcu każdego żądania (np. za flagą środowiskowąOXPHP_DEV), aby zrecyklingować worker, co ponownie wykona zewnętrzny zakres i uwzględni wszystkie zmiany. - Cache na poziomie frameworka — skompilowany kontener Symfony, cache tras/konfiguracji/widoków Laravela, zoptymalizowana classmapa Composera. To są pliki
.php, które OPcache rewaliduje, ale wartości w nich zawarte odwołują się do nieaktualnych ścieżek klas lub identyfikatorów kontenera. Uruchom poleceniecache:clearframeworka; sam OPcache nie wystarczy. - Pliki nie-PHP —
.env,composer.json, konfiguracja YAML/JSON, pliki szablonów kompilowane poza OPcache. OPcache śledzi tylko pliki, które sam skompilował; wszystko inne wymaga restartu.
Kompilacja JIT
Kompilator JIT w OPcache tłumaczy opcode'y PHP na natywny kod maszynowy w czasie działania. Użyj trybu tracing, aby uzyskać najlepszą optymalizację:
opcache.jit=tracing
opcache.jit_buffer_size=64MJIT daje największe korzyści dla kodu PHP ograniczonego przez CPU: pętli intensywnie liczących, przetwarzania łańcuchów znaków, manipulacji obrazami i renderowania szablonów. W przypadku aplikacji ograniczonych przez I/O, które większość czasu spędzają, czekając na zapytania do bazy danych lub wywołania zewnętrznych API, poprawa jest minimalna.
Aby wyłączyć JIT:
opcache.jit=disable
opcache.jit_buffer_size=0Preloading
Preloading w OPcache kompiluje i cache'uje pliki PHP przy starcie serwera, zanim obsłużone zostaną jakiekolwiek żądania. Całkowicie eliminuje to koszt kompilacji przy pierwszym żądaniu i udostępnia klasy oraz funkcje globalnie, bez żadnego narzutu związanego z require czy autoloadingiem.
Skonfiguruj preloading w swoim pliku INI:
opcache.preload=/var/www/html/preload.php
opcache.preload_user=www-dataUtwórz skrypt preload.php, który ładuje Twoje najczęściej używane pliki:
<?php
// preload.php — runs once at server startup
require __DIR__ . '/vendor/autoload.php';
// Preload framework core files
$files = glob(__DIR__ . '/vendor/symfony/http-kernel/**.php');
foreach ($files as $file) {
opcache_compile_file($file);
}
// Preload hot application paths
opcache_compile_file(__DIR__ . '/src/Controller/ApiController.php');
opcache_compile_file(__DIR__ . '/src/Service/UserService.php');Klasy i funkcje objęte preloadingiem są trwale dostępne dla wszystkich żądań. Nie można ich zmienić bez restartu serwera.
Jeśli używasz trybu Worker, Twoja aplikacja jest już zainicjalizowana raz: autoloader, konfiguracja i połączenia z bazą danych utrzymują się między żądaniami. Preloading w OPcache uzupełnia to, eliminując narzut kompilacji opcode'ów, ale nie zastępuje inicjalizacji aplikacji. Oba mechanizmy działają niezależnie i można ich używać razem.
Stosowanie konfiguracji PHP
OxPHP odczytuje konfigurację PHP ze standardowego katalogu conf.d. Użyj wolumenu Dockera lub instrukcji COPY, aby dostarczyć swój własny plik INI.
docker run -p 80:80 \
-v ./custom.ini:/usr/local/etc/php/conf.d/custom.ini:ro \
ghcr.io/oxphp/oxphp:0.10.0FROM ghcr.io/oxphp/oxphp:0.10.0
COPY custom.ini /usr/local/etc/php/conf.d/custom.ini
COPY --chown=www-data:www-data . /var/www/htmlservices:
app:
image: ghcr.io/oxphp/oxphp:0.10.0
ports:
- "80:80"
volumes:
- ./custom.ini:/usr/local/etc/php/conf.d/custom.ini:ro
- ./src:/var/www/htmlMonitorowanie stanu cache'u
Sprawdź na żywo stan OPcache z poziomu PHP, aby zweryfikować, że działa:
<?php
$status = opcache_get_status();
echo "Cached scripts: " . $status['opcache_statistics']['num_cached_scripts'] . "\n";
echo "Cache hits: " . $status['opcache_statistics']['hits'] . "\n";
echo "Cache misses: " . $status['opcache_statistics']['misses'] . "\n";
echo "Free memory: " . $status['memory_usage']['free_memory'] . " bytes\n";Jeśli free_memory jest stale niskie, zwiększ opcache.memory_consumption.
Zobacz też
- Przewodnik po Dockerze -- konfiguracja kontenera i montowanie plików konfiguracyjnych
- Dokumentacja konfiguracji -- zmienne środowiskowe dla OxPHP
- Tryb Worker -- trwałe procesy PHP, które najbardziej zyskują na OPcache