Stručně: OPcache je vestavěná bytecode cache PHP. Podle příručky ukládá předkompilovaný bytecode do sdílené paměti, takže PHP nemusí skripty při každém požadavku znovu načítat a překládat. Je součástí dodávky od PHP 5.5.0. OPcache PHP zrychluje, ale nenahrazuje aktualizaci: po záplatě PHP je nutné restartovat všechny procesy PHP, nestačí vyprázdnit cache.
Co přesně OPcache dělá?
Při každém požadavku musí PHP skript přečíst, rozložit a přeložit do opcodů, tedy do příkazů pro virtuální stroj Zend Engine. U CMS se stovkami souborů je to hodně práce, která se neustále opakuje.
OPcache ukládá výsledek tohoto překladu do sdílené paměti (shared memory). Přistupují k ní všichni workeři služby PHP-FPM nebo všechny procesy Apache s mod_php. Pokud se soubor nezmění, jeho bytecode se použije přímo.
OPcache se načítá jako rozšíření Zend, nikoli jako běžné rozšíření:
; Linux (cesta podle balíčku)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll
Podle příručky se má OPcache načítat před Xdebugem, pokud jsou aktivní oba.
Důležité je, komu sdílená paměť patří. U PHP-FPM ji vytváří hlavní proces (master) a využívají ji všichni workeři všech poolů této služby. U mod_php patří k hlavnímu procesu Apache. Restart služby proto cache vyprázdní úplně, jeden nový worker však ne. V příkazové řádce neexistuje sdílená paměť napříč voláními, protože každé volání je samostatný proces; tam je OPcache standardně vypnuta.
Pro rozhodovatele stačí jednoduché pravidlo: OPcache je na produkčních serverech téměř vždy užitečná, vyžaduje ale jasný postup pro nasazování a aktualizace.
Která nastavení OPcache jsou důležitá?
Následující hodnoty pocházejí ze stránky o konfiguraci v příručce PHP. Sloupec „Měnitelné“ ukazuje, kde lze nastavení provést: INI_SYSTEM jen v php.ini nebo v konfiguraci serveru, INI_ALL všude.
| Direktiva | Výchozí | Měnitelné | Význam |
|---|---|---|---|
opcache.enable |
1 | INI_ALL | cache zapnuta nebo vypnuta, za běhu lze jen vypnout |
opcache.enable_cli |
0 | INI_SYSTEM | cache pro příkazovou řádku |
opcache.memory_consumption |
128 | INI_SYSTEM | velikost sdílené paměti v MB |
opcache.interned_strings_buffer |
8 | INI_SYSTEM | paměť pro sdílené řetězce v MB |
opcache.max_accelerated_files |
10000 | INI_SYSTEM | maximální počet skriptů v cache |
opcache.validate_timestamps |
1 | INI_ALL | kontroluje, zda se soubory změnily |
opcache.revalidate_freq |
2 | INI_ALL | interval kontroly v sekundách, 0 = při každém požadavku |
opcache.restrict_api |
prázdné | INI_SYSTEM | povoluje funkce API jen z jedné cesty |
opcache.validate_permission |
0 | INI_SYSTEM | kontroluje oprávnění k souborům vůči aktuálnímu uživateli |
opcache.validate_root |
0 | INI_SYSTEM | zabraňuje kolizím názvů při chroot |
opcache.file_cache |
prázdné | INI_SYSTEM | druhá úroveň cache na disku |
Typická produkční konfigurace by mohla vypadat takto. Hodnoty předem ověřte se svou aplikací:
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
Kdo nastaví opcache.validate_timestamps=0, získá trochu výkonu. OPcache pak ale změněné soubory už vůbec nepozná a každé nasazení vyžaduje reset cache nebo restart.
Sledování cache a cílené vyprazdňování
OPcache má vlastní funkce, mimo jiné opcache_get_status(), opcache_get_configuration(), opcache_invalidate() a opcache_reset(). Krátký pohled jen pro čtení na naplnění:
<?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 serverech s více weby by neměla mít každá aplikace možnost vyprazdňovat nebo číst cache všech ostatních. K tomu slouží opcache.restrict_api: funkce API smějí volat jen skripty pod zadanou cestou.
JIT: kompilátor strojového kódu v OPcache
Od PHP 8.0 obsahuje OPcache kompilátor JIT, který překládá opcody na strojový kód. Podle RFC k JIT je téměř samostatnou součástí OPcache a vytvořený kód ukládá do vlastní oblasti sdílené paměti. Řídí se pomocí opcache.jit a opcache.jit_buffer_size. Od PHP 8.4.0 je opcache.jit standardně nastaveno na disable. Kdy se JIT vyplatí, vysvětluje článek JIT a výkon v PHP 8.
OPcache a bezpečnost: co platí po PHP2Shell
OPcache není bezpečnostní nástroj, má ale důsledky pro bezpečnost. Po PHP2Shell jsou důležité tři body:
- Reset cache není aktualizace.
opcache_reset()vyprázdní jen skripty v cache. Interpret se zranitelnostmi CVE-2026-109618 a CVE-2026-109619 zůstává v paměti, dokud nejsou restartovány všechny procesy. Jak na to, popisuje článek Restart PHP-FPM a všech workerů. - Vložený kód může v cache přežít. Pokud byl soubor zmanipulován a později nahrazen, může se při vypnuté kontrole časových razítek dál provádět stará verze. Po vyčištění proto patří k postupu restart.
- Sdílená paměť vyžaduje oddělení. Na serverech s více zákazníky pomáhají samostatné pooly PHP-FPM pro každý web a také
opcache.validate_permissionaopcache.restrict_api. Adresář proopcache.file_cachesmí být zapisovatelný jen pro uživatele PHP.
Po každé aktualizaci zkontrolujte, zda je doba spuštění procesů PHP později než aktualizace. Plná OPcache s vysokou úspěšností není důkazem, že běží nový interpret.
Jak konkrétně pomáhá PHP SOS?
- Zkontrolovat konfiguraci: Načteme aktivní konfiguraci OPcache pro každý provozní režim a porovnáme ji s vaší aplikací.
- Zabezpečit nasazování: Zavedeme pevný postup pro reset cache a restart, aby nepokračovala žádná stará verze kódu.
- Oddělit klienty: V rámci zpevnění serveru nastavíme oddělené pooly,
restrict_apia vhodná oprávnění. - Kontrolovat po aktualizacích: Podle časů spuštění procesů doložíme, že aktualizovaný interpret skutečně běží.
Časté dotazy
Je OPcache standardně aktivní?
OPcache se s PHP dodává od PHP 5.5.0 a podle příručky běží s výchozím nastavením opcache.enable=1, jakmile je rozšíření načteno. Zda je načteno, závisí na vašem balíčku nebo poskytovateli hostingu. V příkazové řádce je OPcache naopak standardně vypnuta (opcache.enable_cli=0).
Proč po nasazení stále vidím starý kód?
Pravděpodobně OPcache kontroluje změny souborů jen v intervalech, nebo vůbec. S opcache.revalidate_freq čeká standardně dvě sekundy, s opcache.validate_timestamps=0 nikdy. Pak pomůže jen reset cache nebo restart PHP-FPM, resp. Apache.
Stačí po aktualizaci PHP opcache_reset()?
Ne. opcache_reset() vyprázdní jen cache s přeloženými skripty. Aktualizace PHP nahrazuje samotný interpret a ten je načten v každém běžícím procesu. K tomu je nutné restartovat všechny procesy PHP.
Je JIT v PHP 8.4 zapnutý?
Podle příručky je opcache.jit od PHP 8.4.0 standardně nastaveno na disable, zatímco opcache.jit_buffer_size činí 64M. Dříve to bylo naopak: jit na tracing, vyrovnávací paměť na 0. V obou případech není JIT bez vědomé konfigurace aktivní.