Stručne: OPcache je vstavaná bytecode cache PHP. Podľa príručky ukladá vopred skompilovaný bytecode do zdieľanej pamäte, takže PHP nemusí skripty pri každej požiadavke znova načítavať a prekladať. Je súčasťou balíka od PHP 5.5.0. OPcache robí PHP rýchlejším, ale nenahrádza aktualizáciu: po záplate PHP sa musia reštartovať všetky procesy PHP, nestačí vyprázdniť cache.
Čo presne OPcache robí?
Pri každej požiadavke musí PHP skript prečítať, rozložiť a preložiť na opcódy, teda príkazy pre virtuálny stroj Zend Engine. Pri CMS so stovkami súborov je to veľa práce, ktorá sa neustále opakuje.
OPcache ukladá výsledok tohto prekladu do zdieľanej pamäte (Shared Memory). Pristupujú k nej všetky workery služby PHP-FPM alebo všetky procesy Apache s mod_php. Ak sa súbor nezmení, jeho bytecode sa použije priamo znova.
OPcache sa načítava ako rozšírenie Zend, nie ako bežné rozšírenie:
; Linux (cesta podľa balíka)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll
Podľa príručky sa má OPcache načítať pred Xdebug, ak sú aktívne obe.
Dôležité je, komu zdieľaná pamäť patrí. Pri PHP-FPM ju vytvára hlavný proces (master) a využívajú ju všetky workery všetkých poolov tejto služby. Pri mod_php patrí hlavnému procesu Apache. Reštart služby preto cache vyprázdni úplne, jeden nový worker však nie. Pre príkazový riadok neexistuje zdieľaná pamäť medzi jednotlivými volaniami, pretože každé volanie je samostatný proces; tam je OPcache štandardne vypnutá.
Pre rozhodovateľov postačí pravidlo palca: OPcache je na produkčných serveroch takmer vždy užitočná, vyžaduje však jasný postup pri nasadzovaní a aktualizáciách.
Ktoré nastavenia OPcache sú dôležité?
Nasledujúce hodnoty pochádzajú zo stránky konfigurácie v príručke PHP. Stĺpec „Meniteľné“ ukazuje, kde sa nastavenie smie zadať: INI_SYSTEM len v php.ini alebo v konfigurácii servera, INI_ALL všade.
| Direktíva | Štandard | Meniteľné | Význam |
|---|---|---|---|
opcache.enable |
1 | INI_ALL | cache zapnutá alebo vypnutá, počas behu sa dá len vypnúť |
opcache.enable_cli |
0 | INI_SYSTEM | cache pre príkazový riadok |
opcache.memory_consumption |
128 | INI_SYSTEM | veľkosť zdieľanej pamäte v MB |
opcache.interned_strings_buffer |
8 | INI_SYSTEM | pamäť pre spoločné reťazce znakov v MB |
opcache.max_accelerated_files |
10000 | INI_SYSTEM | maximálny počet skriptov v cache |
opcache.validate_timestamps |
1 | INI_ALL | kontroluje, či sa súbory zmenili |
opcache.revalidate_freq |
2 | INI_ALL | interval kontroly v sekundách, 0 = pri každej požiadavke |
opcache.restrict_api |
prázdne | INI_SYSTEM | povoľuje funkcie API iba z jednej cesty |
opcache.validate_permission |
0 | INI_SYSTEM | kontroluje práva súborov voči aktuálnemu používateľovi |
opcache.validate_root |
0 | INI_SYSTEM | zabraňuje kolíziám názvov pri chroot |
opcache.file_cache |
prázdne | INI_SYSTEM | druhá úroveň cache na disku |
Typická produkčná konfigurácia by mohla vyzerať takto. Hodnoty si vopred overte so svojou aplikáciou:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.restrict_api=/var/www/admin-tools
Kto nastaví opcache.validate_timestamps=0, získa trochu výkonu. OPcache potom však zmenené súbory vôbec nerozpozná a každé nasadenie vyžaduje reset cache alebo reštart.
Sledovanie cache a cielené vyprázdnenie
OPcache prináša vlastné funkcie, medzi nimi opcache_get_status(), opcache_get_configuration(), opcache_invalidate() a opcache_reset(). Krátky pohľad na zaplnenie, len na čítanie:
<?php
$status = opcache_get_status(false);
if ($status === false) {
exit("OPcache ist nicht aktiv.\n");
}
printf("Gecachte Skripte: %d\n", $status['opcache_statistics']['num_cached_scripts']);
printf("Freier Speicher: %.1f MB\n", $status['memory_usage']['free_memory'] / 1048576);
Na serveroch s viacerými webmi by nemala každá aplikácia vedieť vyprázdniť alebo čítať cache všetkých ostatných. Na to slúži opcache.restrict_api: funkcie API smú volať iba skripty pod zadanou cestou.
JIT: kompilátor strojového kódu v OPcache
Od PHP 8.0 obsahuje OPcache kompilátor JIT, ktorý prekladá opcódy na strojový kód. Podľa RFC k JIT je to takmer samostatná súčasť OPcache a vytvorený kód ukladá do vlastnej oblasti zdieľanej pamäte. Riadi sa pomocou opcache.jit a opcache.jit_buffer_size. Od PHP 8.4.0 je opcache.jit štandardne nastavený na disable. Kedy sa JIT oplatí, vysvetľuje príspevok JIT a výkon v PHP 8.
OPcache a bezpečnosť: čo platí po PHP2Shell
OPcache nie je bezpečnostný nástroj, ale má dôsledky pre bezpečnosť. Po PHP2Shell sú dôležité tri body:
- Reset cache nie je aktualizácia.
opcache_reset()vyprázdni len skripty v cache. Interpreter so zraniteľnosťami CVE-2026-109618 a CVE-2026-109619 zostáva v pamäti, kým sa nereštartujú všetky procesy. Ako na to, je na stránke Reštart PHP-FPM a všetkých workerov. - Votknutý kód môže v cache žiť ďalej. Ak bol súbor zmanipulovaný a neskôr nahradený, pri vypnutej kontrole časových pečiatok sa môže ďalej vykonávať stará verzia. Po vyčistení preto patrí k veci aj reštart.
- Zdieľaná pamäť vyžaduje oddelenie. Na serveroch s viacerými zákazníkmi pomáhajú samostatné pooly PHP-FPM pre každý web, ako aj
opcache.validate_permissionaopcache.restrict_api. Adresár preopcache.file_cachesmie byť zapisovateľný iba pre používateľa PHP.
Po každej aktualizácii skontrolujte, či je čas spustenia procesov PHP neskorší než aktualizácia. Plná OPcache s vysokou úspešnosťou nie je dôkazom, že beží nový interpreter.
Ako konkrétne pomáha PHP SOS?
- Skontrolovať konfiguráciu: Zisťujeme aktívnu konfiguráciu OPcache podľa režimu prevádzky a porovnávame ju s vašou aplikáciou.
- Zabezpečiť nasadzovanie: Zavedieme pevný postup pre reset cache a reštart, aby nebežala žiadna stará verzia kódu.
- Oddeliť klientov: V rámci zabezpečenia servera (hardening) nastavujeme oddelené pooly,
restrict_apia vhodné práva. - Kontrolovať po aktualizáciách: Podľa časov spustenia procesov preukážeme, že aktualizovaný interpreter skutočne beží.
Časté otázky
Je OPcache štandardne aktívna?
OPcache sa dodáva s PHP od verzie 5.5.0 a podľa príručky beží s opcache.enable=1 ako štandard, len čo je rozšírenie načítané. To, či je načítané, závisí od vášho balíka alebo poskytovateľa hostingu. V príkazovom riadku je OPcache naopak štandardne vypnutá (opcache.enable_cli=0).
Prečo po nasadení stále vidím starý kód?
Pravdepodobne OPcache kontroluje zmeny súborov len v intervaloch alebo vôbec. S opcache.revalidate_freq čaká štandardne dve sekundy, s opcache.validate_timestamps=0 nikdy. Vtedy pomôže iba reset cache alebo reštart PHP-FPM, resp. Apache.
Stačí opcache_reset() po aktualizácii PHP?
Nie. opcache_reset() vyprázdni iba cache s preloženými skriptmi. Aktualizácia PHP nahrádza samotný interpreter a ten je načítaný v každom bežiacom procese. Preto sa musia reštartovať všetky procesy PHP.
Je JIT v PHP 8.4 zapnutý?
Podľa príručky je opcache.jit od PHP 8.4.0 štandardne nastavený na disable, kým opcache.jit_buffer_size má 64M. Predtým to bolo naopak: jit na tracing, vyrovnávacia pamäť na 0. V oboch prípadoch nie je JIT bez vedomej konfigurácie aktívny.