Kort sagt: OPcache är PHP:s inbyggda bytekodcache. Enligt manualen lagrar den förkompilerad bytekod i delat minne, så att PHP inte behöver läsa in och översätta skript vid varje förfrågan. Den ingår i leveransen sedan PHP 5.5.0. OPcache gör PHP snabbare men ersätter ingen uppdatering: Efter en PHP-patch måste alla PHP-processer startas om, det räcker inte att tömma cachen.
Vad gör OPcache egentligen?
Vid varje förfrågan måste PHP läsa ett skript, dela upp det och översätta det till opcodes, alltså kommandona för den virtuella maskinen i Zend Engine. För ett CMS med hundratals filer är det mycket arbete som ständigt upprepas.
OPcache lagrar resultatet av den översättningen i delat minne (shared memory). Alla workers i en PHP-FPM-tjänst eller alla Apache-processer med mod_php använder det. Ändras en fil inte återanvänds dess bytekod direkt.
OPcache laddas som Zend-tillägg, inte som ett vanligt tillägg:
; Linux (sökväg beroende på paket)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll
Enligt manualen ska OPcache laddas före Xdebug om båda är aktiva.
Vem som äger det delade minnet är viktigt. Med PHP-FPM skapar masterprocessen det, och alla workers i alla pooler i den tjänsten använder det. Med mod_php hör det till Apache-huvudprocessen. En omstart av tjänsten tömmer därför cachen helt, medan en enskild ny worker inte gör det. För kommandoraden finns inget delat minne mellan anropen, eftersom varje anrop är en egen process; där är OPcache som standard avstängd.
För beslutsfattare räcker en tumregel: OPcache är på produktionsservrar nästan alltid meningsfull men kräver ett tydligt förfarande för driftsättningar och uppdateringar.
Vilka OPcache-inställningar räknas?
Följande värden kommer från konfigurationssidan i PHP-manualen. Kolumnen ”Ändringsbar” visar var en inställning får sättas: INI_SYSTEM bara i php.ini eller serverkonfigurationen, INI_ALL överallt.
| Direktiv | Standard | Ändringsbar | Betydelse |
|---|---|---|---|
opcache.enable |
1 | INI_ALL | cache på eller av, vid körning går den bara att stänga av |
opcache.enable_cli |
0 | INI_SYSTEM | cache för kommandoraden |
opcache.memory_consumption |
128 | INI_SYSTEM | storlek på det delade minnet i MB |
opcache.interned_strings_buffer |
8 | INI_SYSTEM | minne för gemensamma teckensträngar i MB |
opcache.max_accelerated_files |
10000 | INI_SYSTEM | maximalt antal cachade skript |
opcache.validate_timestamps |
1 | INI_ALL | kontrollerar om filer har ändrats |
opcache.revalidate_freq |
2 | INI_ALL | kontrollintervall i sekunder, 0 = vid varje förfrågan |
opcache.restrict_api |
tom | INI_SYSTEM | tillåter API-funktioner bara från en viss sökväg |
opcache.validate_permission |
0 | INI_SYSTEM | kontrollerar filrättigheter mot aktuell användare |
opcache.validate_root |
0 | INI_SYSTEM | förhindrar namnkollisioner vid chroot |
opcache.file_cache |
tom | INI_SYSTEM | andra cachenivå på disken |
En typisk produktionskonfiguration kan se ut så här. Kontrollera värdena med er applikation i förväg:
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
Den som sätter opcache.validate_timestamps=0 vinner lite prestanda. Då upptäcker OPcache dock inte längre ändrade filer alls, och varje driftsättning kräver en återställning av cachen eller en omstart.
Iaktta cachen och tömma den riktat
OPcache har egna funktioner, bland annat opcache_get_status(), opcache_get_configuration(), opcache_invalidate() och opcache_reset(). En kort, enbart läsande titt på fyllnadsgraden:
<?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);
På servrar med flera webbplatser bör inte varje applikation kunna tömma eller läsa ut alla andras cache. Det är vad opcache.restrict_api är till för: Bara skript under den angivna sökvägen får anropa API-funktionerna.
JIT: maskinkodskompilatorn i OPcache
Sedan PHP 8.0 innehåller OPcache en JIT-kompilator som översätter opcodes till maskinkod. Enligt JIT-RFC:t är den en nästan fristående del av OPcache och lägger den skapade koden i ett eget område i det delade minnet. Den styrs med opcache.jit och opcache.jit_buffer_size. Sedan PHP 8.4.0 står opcache.jit som standard på disable. När JIT lönar sig förklaras i artikeln JIT och prestanda i PHP 8.
OPcache och säkerhet: vad som gäller efter PHP2Shell
OPcache är inget säkerhetsverktyg men får konsekvenser för säkerheten. Tre punkter är viktiga efter PHP2Shell:
- En cache-återställning är ingen uppdatering.
opcache_reset()tömmer bara cachade skript. Tolken med sårbarheterna CVE-2026-109618 och CVE-2026-109619 finns kvar i minnet tills alla processer har startats om. Hur det går till står under Starta om PHP-FPM och alla workers. - Insmugglad kod kan leva vidare i cachen. Om en fil har manipulerats och senare ersatts kan den gamla versionen fortsätta köras när tidsstämpelkontrollen är avstängd. Efter en sanering hör därför en omstart till.
- Delat minne kräver åtskillnad. På servrar med flera kunder hjälper egna PHP-FPM-pooler per webbplats samt
opcache.validate_permissionochopcache.restrict_api. En katalog föropcache.file_cachefår bara vara skrivbar för PHP-användaren.
Kontrollera efter varje uppdatering att PHP-processernas starttid ligger efter uppdateringen. En full OPcache med hög träffprocent är inget bevis för att den nya tolken körs.
Hur hjälper PHP SOS konkret?
- Kontrollera konfigurationen: Vi läser ut den aktiva OPcache-konfigurationen per driftläge och jämför den med er applikation.
- Säkra driftsättningar: Vi inför ett fast förfarande för cache-återställning och omstart, så att ingen gammal kodversion fortsätter att köras.
- Skilja mandanter åt: Inom ramen för serverhärdning sätter vi åtskilda pooler,
restrict_apioch lämpliga rättigheter. - Kontrollera efter uppdateringar: Vi styrker via processernas starttider att den uppdaterade tolken verkligen är aktiv.
Vanliga frågor
Är OPcache aktiv som standard?
OPcache levereras med PHP sedan PHP 5.5.0 och körs enligt manualen med opcache.enable=1 som standard så snart tillägget är laddat. Om det är laddat beror på ert paket eller webbhotell. På kommandoraden är OPcache däremot som standard avstängd (opcache.enable_cli=0).
Varför ser jag fortfarande den gamla koden efter en driftsättning?
Troligen kontrollerar OPcache filändringar bara med intervall eller inte alls. Med opcache.revalidate_freq väntar den som standard två sekunder, med opcache.validate_timestamps=0 aldrig. Då hjälper bara en återställning av cachen eller en omstart av PHP-FPM respektive Apache.
Räcker opcache_reset() efter en PHP-uppdatering?
Nej. opcache_reset() tömmer bara cachen med översatta skript. En PHP-uppdatering ersätter själva tolken, och den är laddad i varje pågående process. Därför måste alla PHP-processer startas om.
Är JIT påslagen i PHP 8.4?
Enligt manualen är opcache.jit sedan PHP 8.4.0 som standard satt till disable, medan opcache.jit_buffer_size är 64M. Tidigare var det tvärtom: jit på tracing, buffert på 0. I båda fallen är JIT inte aktiv utan medveten konfiguration.