Ukratko: OPcache je ugrađena PHP-ova predmemorija bytecodea. Prema priručniku pohranjuje unaprijed kompiliran bytecode u zajedničku memoriju, pa PHP skripte ne mora pri svakom zahtjevu iznova učitavati i prevoditi. Dio je isporuke od PHP-a 5.5.0. OPcache ubrzava PHP, ali ne zamjenjuje ažuriranje: nakon PHP zakrpe moraju se ponovno pokrenuti svi PHP procesi, a ne samo isprazniti predmemorija.
Što točno radi OPcache?
Pri svakom zahtjevu PHP mora pročitati skriptu, rastaviti je i prevesti u opcodeove, dakle u naredbe za virtualni stroj Zend Enginea. Kod CMS-a sa stotinama datoteka to je puno posla koji se neprestano ponavlja.
OPcache rezultat tog prevođenja sprema u zajedničku memoriju (shared memory). Pristupaju joj svi workeri jedne PHP-FPM usluge odnosno svi Apache procesi s mod_php-om. Ako se datoteka ne promijeni, njezin se bytecode izravno ponovno koristi.
OPcache se učitava kao Zend ekstenzija, a ne kao obična ekstenzija:
; Linux (putanja ovisi o paketu)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll
Prema priručniku OPcache treba učitati prije Xdebuga ako su oba aktivna.
Važno je kome pripada zajednička memorija. Kod PHP-FPM-a nju stvara master proces, a koriste je svi workeri svih poolova te usluge. Kod mod_php-a pripada glavnom procesu Apachea. Ponovno pokretanje usluge stoga potpuno prazni predmemoriju, a jedan novi worker ne. Za naredbeni redak ne postoji zajednička memorija među pozivima jer je svaki poziv zaseban proces; tamo je OPcache prema zadanim postavkama isključen.
Za donositelje odluka dovoljno je jedno pravilo: OPcache je na produkcijskim poslužiteljima gotovo uvijek smislen, ali traži jasan slijed za deploymente i ažuriranja.
Koje OPcache postavke vrijede?
Sljedeće vrijednosti potječu sa stranice konfiguracije PHP priručnika. Stupac „Promjenjivo“ pokazuje gdje se postavka smije podešavati: INI_SYSTEM samo u php.ini ili konfiguraciji poslužitelja, INI_ALL posvuda.
| Direktiva | Zadano | Promjenjivo | Značenje |
|---|---|---|---|
opcache.enable |
1 | INI_ALL | predmemorija uključena ili isključena, tijekom rada može se samo isključiti |
opcache.enable_cli |
0 | INI_SYSTEM | predmemorija za naredbeni redak |
opcache.memory_consumption |
128 | INI_SYSTEM | veličina zajedničke memorije u MB |
opcache.interned_strings_buffer |
8 | INI_SYSTEM | memorija za zajedničke nizove znakova u MB |
opcache.max_accelerated_files |
10000 | INI_SYSTEM | najveći broj skripti u predmemoriji |
opcache.validate_timestamps |
1 | INI_ALL | provjerava jesu li se datoteke promijenile |
opcache.revalidate_freq |
2 | INI_ALL | razmak provjere u sekundama, 0 = pri svakom zahtjevu |
opcache.restrict_api |
prazno | INI_SYSTEM | dopušta API funkcije samo iz jedne putanje |
opcache.validate_permission |
0 | INI_SYSTEM | provjerava prava datoteka u odnosu na trenutnog korisnika |
opcache.validate_root |
0 | INI_SYSTEM | sprječava sukobe naziva kod chroota |
opcache.file_cache |
prazno | INI_SYSTEM | druga razina predmemorije na disku |
Tipična produkcijska konfiguracija mogla bi izgledati ovako. Vrijednosti prije provjerite sa svojom aplikacijom:
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
Tko postavi opcache.validate_timestamps=0, dobiva malo učinkovitosti. No tada OPcache uopće više ne prepoznaje izmijenjene datoteke i svaki deployment traži reset predmemorije ili ponovno pokretanje.
Promatrati predmemoriju i ciljano je prazniti
OPcache donosi vlastite funkcije, među ostalim opcache_get_status(), opcache_get_configuration(), opcache_invalidate() i opcache_reset(). Kratak pogled samo za čitanje na popunjenost:
<?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 poslužiteljima s više web-stranica ne bi svaka aplikacija smjela moći prazniti ili čitati predmemoriju svih ostalih. Za to služi opcache.restrict_api: API funkcije smiju pozivati samo skripte ispod navedene putanje.
JIT: kompilator strojnog koda u OPcacheu
Od PHP-a 8.0 OPcache sadrži JIT kompilator koji opcodeove prevodi u strojni kod. Prema JIT RFC-u gotovo je samostalan dio OPcachea i stvoreni kod sprema u zasebno područje zajedničke memorije. Upravlja se putem opcache.jit i opcache.jit_buffer_size. Od PHP-a 8.4.0 opcache.jit je prema zadanim postavkama disable. Kada se JIT isplati, objašnjava članak JIT i performanse u PHP-u 8.
OPcache i sigurnost: što vrijedi nakon PHP2Shella
OPcache nije sigurnosni alat, ali ima posljedice za sigurnost. Tri su točke važne nakon PHP2Shella:
- Reset predmemorije nije ažuriranje.
opcache_reset()prazni samo skripte u predmemoriji. Interpreter s ranjivostima CVE-2026-109618 i CVE-2026-109619 ostaje u memoriji dok se svi procesi ne pokrenu iznova. Kako to ide, piše na stranici Ponovno pokretanje PHP-FPM-a i svih workera. - Ubačeni kod može živjeti u predmemoriji. Ako je datoteka bila manipulirana, a kasnije zamijenjena, uz isključenu provjeru vremenskih oznaka stara se izvedba može i dalje izvršavati. Nakon čišćenja zato treba i ponovno pokretanje.
- Zajednička memorija traži razdvajanje. Na poslužiteljima s više klijenata pomažu vlastiti PHP-FPM poolovi po web-stranici te
opcache.validate_permissioniopcache.restrict_api. Direktorij zaopcache.file_cachesmije biti upisiv samo za PHP korisnika.
Nakon svakog ažuriranja provjerite je li vrijeme pokretanja PHP procesa poslije ažuriranja. Pun OPcache s visokom stopom pogodaka nije dokaz da radi novi interpreter.
Kako PHP SOS konkretno pomaže?
- Provjeriti konfiguraciju: Očitavamo aktivnu OPcache konfiguraciju po načinu rada i uspoređujemo je s Vašom aplikacijom.
- Osigurati deploymente: Uspostavljamo čvrst slijed za reset predmemorije i ponovno pokretanje kako nijedna stara izvedba koda ne bi nastavila raditi.
- Razdvojiti klijente: U okviru ojačavanja poslužitelja postavljamo odvojene poolove,
restrict_apii odgovarajuća prava. - Provjeriti nakon ažuriranja: Putem vremena pokretanja procesa dokazujemo da je ažurirani interpreter stvarno aktivan.
Česta pitanja
Je li OPcache prema zadanim postavkama aktivan?
OPcache se isporučuje s PHP-om od verzije 5.5.0 i prema priručniku radi s opcache.enable=1 kao zadanom vrijednosti čim se ekstenzija učita. Je li učitana, ovisi o Vašem paketu ili pružatelju hostinga. U naredbenom retku OPcache je, naprotiv, prema zadanim postavkama isključen (opcache.enable_cli=0).
Zašto nakon deploymenta još vidim stari kod?
Vjerojatno OPcache izmjene datoteka provjerava samo u razmacima ili uopće ne. S opcache.revalidate_freq prema zadanim postavkama čeka dvije sekunde, a s opcache.validate_timestamps=0 nikad. Tada pomaže samo reset predmemorije ili ponovno pokretanje PHP-FPM-a odnosno Apachea.
Je li opcache_reset() dovoljan nakon ažuriranja PHP-a?
Ne. opcache_reset() prazni samo predmemoriju s prevedenim skriptama. Ažuriranje PHP-a zamjenjuje sam interpreter, a on je učitan u svakom pokrenutom procesu. Zato se moraju ponovno pokrenuti svi PHP procesi.
Je li JIT uključen u PHP-u 8.4?
Prema priručniku opcache.jit je od PHP-a 8.4.0 prema zadanim postavkama postavljen na disable, dok opcache.jit_buffer_size iznosi 64M. Prije je bilo obrnuto: jit na tracing, međuspremnik na 0. U oba slučaja JIT bez svjesne konfiguracije nije aktivan.