Na kratko: OPcache je vgrajeni predpomnilnik bajtne kode PHP. Po priročniku v skupni pomnilnik shrani vnaprej prevedeno bajtno kodo, tako da PHP skript ob vsaki zahtevi ni treba znova nalagati in prevajati. V dobavljenem obsegu je od PHP 5.5.0. OPcache PHP pospeši, vendar ne nadomešča posodobitve: po popravku PHP je treba znova zagnati vse procese PHP, ne samo izprazniti predpomnilnika.
Kaj točno počne OPcache?
Ob vsaki zahtevi mora PHP skripto prebrati, razčleniti in prevesti v opcode, torej v ukaze za navidezni stroj Zend Engine. Pri CMS-ju s stotinami datotek je to veliko dela, ki se nenehno ponavlja.
OPcache rezultat tega prevajanja shrani v skupni pomnilnik (shared memory). Do njega dostopajo vsi workerji storitve PHP-FPM ali vsi procesi Apache z mod_php. Če se datoteka ne spremeni, se njena bajtna koda neposredno ponovno uporabi.
OPcache se naloži kot razširitev Zend, ne kot navadna razširitev:
; Linux (pot je odvisna od paketa)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll
Po priročniku naj se OPcache naloži pred Xdebug, kadar sta aktivna oba.
Pomembno je, čigav je skupni pomnilnik. Pri PHP-FPM ga ustvari glavni proces, uporabljajo pa ga vsi workerji vseh poolov te storitve. Pri mod_php pripada glavnemu procesu Apache. Ponovni zagon storitve zato predpomnilnik v celoti izprazni, en sam nov worker pa ne. Za ukazno vrstico skupnega pomnilnika med klici ni, ker je vsak klic samostojen proces; tam je OPcache privzeto izklopljen.
Za odločevalce zadošča pravilo palca: OPcache je na produkcijskih strežnikih skoraj vedno smiseln, a zahteva jasen potek namestitev in posodobitev.
Katere nastavitve OPcache štejejo?
Naslednje vrednosti izvirajo iz strani s konfiguracijo v priročniku PHP. Stolpec „Spremenljivo“ kaže, kje se nastavitev sme določiti: INI_SYSTEM samo v php.ini ali konfiguraciji strežnika, INI_ALL povsod.
| Direktiva | Privzeto | Spremenljivo | Pomen |
|---|---|---|---|
opcache.enable |
1 | INI_ALL | predpomnilnik vklopljen ali izklopljen, med izvajanjem ga je mogoče samo izklopiti |
opcache.enable_cli |
0 | INI_SYSTEM | predpomnilnik za ukazno vrstico |
opcache.memory_consumption |
128 | INI_SYSTEM | velikost skupnega pomnilnika v MB |
opcache.interned_strings_buffer |
8 | INI_SYSTEM | pomnilnik za skupne nize znakov v MB |
opcache.max_accelerated_files |
10000 | INI_SYSTEM | največje število predpomnjenih skript |
opcache.validate_timestamps |
1 | INI_ALL | preverja, ali so se datoteke spremenile |
opcache.revalidate_freq |
2 | INI_ALL | razmik preverjanja v sekundah, 0 = ob vsaki zahtevi |
opcache.restrict_api |
prazno | INI_SYSTEM | funkcije API dovoli samo iz ene poti |
opcache.validate_permission |
0 | INI_SYSTEM | preverja pravice datotek glede na trenutnega uporabnika |
opcache.validate_root |
0 | INI_SYSTEM | preprečuje trke imen pri chroot |
opcache.file_cache |
prazno | INI_SYSTEM | druga raven predpomnilnika na disku |
Značilna produkcijska konfiguracija bi lahko izgledala takole. Vrednosti pred tem preverite z vašo aplikacijo:
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
Kdor nastavi opcache.validate_timestamps=0, pridobi nekaj zmogljivosti. Takrat pa OPcache spremenjenih datotek sploh ne prepozna več in vsaka namestitev potrebuje ponastavitev predpomnilnika ali ponovni zagon.
Opazovanje in ciljno praznjenje predpomnilnika
OPcache prinaša lastne funkcije, med njimi opcache_get_status(), opcache_get_configuration(), opcache_invalidate() in opcache_reset(). Kratek bralni pogled na zasedenost:
<?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 strežnikih z več spletnimi stranmi ne bi smela vsaka aplikacija moči izprazniti ali brati predpomnilnika vseh drugih. Za to je namenjen opcache.restrict_api: funkcije API smejo klicati samo skripte pod navedeno potjo.
JIT: prevajalnik strojne kode v OPcache
Od PHP 8.0 OPcache vsebuje prevajalnik JIT, ki opcode prevede v strojno kodo. Po RFC za JIT je skoraj samostojen del OPcache in ustvarjeno kodo shrani v lasten predel skupnega pomnilnika. Upravlja se ga z opcache.jit in opcache.jit_buffer_size. Od PHP 8.4.0 je opcache.jit privzeto na disable. Kdaj se JIT splača, razlaga prispevek JIT in zmogljivost v PHP 8.
OPcache in varnost: kaj velja po PHP2Shell
OPcache ni varnostno orodje, a ima posledice za varnost. Po PHP2Shell so pomembne tri točke:
- Ponastavitev predpomnilnika ni posodobitev.
opcache_reset()izprazni samo predpomnjene skripte. Interpreter z ranljivostma CVE-2026-109618 in CVE-2026-109619 ostane v pomnilniku, dokler niso vsi procesi znova zagnani. Kako, piše na strani Ponovni zagon PHP-FPM in vseh workerjev. - Vnesena koda lahko živi naprej v predpomnilniku. Če je bila datoteka spremenjena in pozneje zamenjana, se pri izklopljenem preverjanju časovnih žigov lahko stara različica še naprej izvaja. Po čiščenju zato sodi zraven ponovni zagon.
- Skupni pomnilnik zahteva ločevanje. Na strežnikih z več strankami pomagajo lastni pooli PHP-FPM za vsako spletno stran ter
opcache.validate_permissioninopcache.restrict_api. Imenik zaopcache.file_cachesme biti zapisljiv samo za uporabnika PHP.
Po vsaki posodobitvi preverite, ali je čas zagona procesov PHP po posodobitvi. Poln OPcache z visokim deležem zadetkov ni dokaz, da teče novi interpreter.
Kako PHP SOS pomaga konkretno?
- Preverjanje konfiguracije: preberemo aktivno konfiguracijo OPcache za vsak način delovanja in jo uskladimo z vašo aplikacijo.
- Zavarovanje namestitev: vzpostavimo trden potek ponastavitve predpomnilnika in ponovnega zagona, da ne teče nobena stara različica kode.
- Ločevanje strank: v okviru utrjevanja strežnika nastavimo ločene poole,
restrict_apiin ustrezne pravice. - Kontrola po posodobitvah: prek časov zagona procesov dokažemo, da posodobljeni interpreter resnično teče.
Pogosta vprašanja
Ali je OPcache privzeto aktiven?
OPcache se dobavlja s PHP od različice 5.5.0 in po priročniku teče z opcache.enable=1 kot privzeto vrednostjo, ko je razširitev naložena. Ali je naložena, je odvisno od vašega paketa ali ponudnika gostovanja. V ukazni vrstici je OPcache privzeto izklopljen (opcache.enable_cli=0).
Zakaj po namestitvi še vedno vidim staro kodo?
Verjetno OPcache spremembe datotek preverja samo v presledkih ali sploh ne. Z opcache.revalidate_freq privzeto čaka dve sekundi, z opcache.validate_timestamps=0 nikoli. Takrat pomaga samo ponastavitev predpomnilnika ali ponovni zagon PHP-FPM oziroma Apacheja.
Ali po posodobitvi PHP zadošča opcache_reset()?
Ne. opcache_reset() izprazni samo predpomnilnik s prevedenimi skriptami. Posodobitev PHP zamenja interpreter sam, ta pa je naložen v vsakem tekočem procesu. Za to je treba znova zagnati vse procese PHP.
Ali je JIT v PHP 8.4 vklopljen?
Po priročniku je opcache.jit od PHP 8.4.0 privzeto nastavljen na disable, opcache.jit_buffer_size pa znaša 64M. Prej je bilo obratno: jit na tracing, medpomnilnik na 0. V obeh primerih JIT brez zavestne konfiguracije ni aktiven.