PHP OPcache versnelt mijn scripts omdat PHP de gecompileerde bytecode in het geheugen bewaart en zo opnieuw parseren overbodig maakt. In deze handleiding laat ik zien hoe ik OPcache configureren, monitor en stem ik alles nauwkeurig af, zodat uw applicatie meetbaar sneller reageert en piekbelastingen moeiteloos opvangt.
Centrale punten
- Bytecode-cache verlaagt CPU-belasting en I/O
- Parameters hoe memory_consumption en max_accelerated_files gericht te kiezen
- Omgeving gedifferentieerd instellen: Dev, Staging, Productie
- Controle gebruiken voor hitrate, bezetting, evictions
- Inzet en cache-flush netjes integreren
Zo werkt OPcache: bytecode in plaats van hercompileren
Bij elke aanvraag leest PHP normaal gesproken bestanden in, parseert de code en maakt bytecode, die door de Zend Engine wordt uitgevoerd. OPcache komt hier precies om de hoek kijken en slaat deze bytecode op in het gedeelde geheugen, zodat volgende verzoeken direct vanuit het geheugen kunnen worden gestart. Hierdoor nemen de CPU-cycli en bestandsaccessen af, wat de responstijden aanzienlijk verkort. In typische opstellingen bereik ik hiermee winst tussen 30 en 70 procent, afhankelijk van de codebasis en het verkeersprofiel. Het is van cruciaal belang dat de cache groot genoeg blijft en dat de belangrijkste scripts permanent in het Geheugen blijven.
OPcache controleren en activeren op Linux, Windows en shared hosting
Ik begin altijd met een blik in phpinfo() en zoek naar „Zend". OPcache“ en sleutels zoals opcache.enable of opcache.memory_consumption. Onder Linux activeer ik de module via het pakket php-opcache en een opcache.ini in de conf.d-map. Onder Windows volstaat een vermelding zend_extension=opcache in php.ini en een herstart van de webserver. Bij shared hosting schakel ik OPcache vaak in via een door de gebruiker gedefinieerde php.ini of via het klantenmenu. Bij knelpunten controleer ik bovendien de PHP-geheugenlimiet verhogen, zodat OPcache en PHP-FPM voldoende Bronnen ontvangen.
De belangrijkste schakelaars duidelijk uitgelegd
Met opcache.enable activeer ik de cache voor webverzoeken, terwijl opcache.enable_cli het gebruik voor CLI-taken regelt, wat de moeite waard is bij worker-queues. De kern wordt gevormd door opcache.memory_consumption, dat het beschikbare gedeelde geheugen in megabytes aangeeft; een te krappe inschatting leidt tot evictions en hernieuwde Compilaties. opcache.max_accelerated_files definieert hoeveel bestanden er in de cache mogen terechtkomen; deze waarde moet het aantal bestanden van het project ruimschoots overschrijden. Met opcache.validate_timestamps en opcache.revalidate_freq bepaal ik hoe streng OPcache wijzigingen in bestanden controleert, van zeer dynamisch (ontwikkeling) tot zeer spaarzaam (productie met handmatige flush). Ik beveilig opmerkingen met opcache.save_comments=1, omdat veel tools op DocBlocks afhankelijk zijn.
Startwaarden en profielen in vergelijking
Voor een soepele start zet ik in op duidelijke profielen voor ontwikkeling, staging en productie. Zo krijg ik enerzijds snelle feedbackcycli bij het coderen en anderzijds betrouwbare prestaties in live-gebruik. Het blijft belangrijk dat u deze startwaarden regelmatig controleert aan de hand van echte statistieken en bijstelt. Bij grotere WordPress-installaties plan ik ruimschoots opslagruimte en vermeldingen in, omdat plug-ins en thema's veel Bestanden genereren. De volgende tabel geeft een overzicht van zinvolle startwaarden, die ik vervolgens op basis van hitrate en evictions nauwkeurig afstel.
| Instelling | Ontwikkeling | Staging/test | Productie |
|---|---|---|---|
| opcache.enable | 1 | 1 | 1 |
| opcache.enable_cli | 0 | 0–1 | 1 (bij CLI-taken) |
| opcache.geheugen_verbruik | 128–256 MB | 256–512 MB | 256–512+ MB |
| opcache.interned_strings_buffer | 16–32 MB | 32–64 MB | 16–64 MB |
| opcache.max_versnelde_bestanden | 8.000–10.000 | 10.000–20.000 | 10.000–20.000+ |
| opcache.validate_timestamps | 1 | 1 | 0–1 (afhankelijk van Deploy) |
| opcache.revalidate_freq | 0–2 s | 60–300 s | 300+ s of 0 (met handmatige controle) |
| opcache.save_comments | 1 | 1 | 1 |
| opcache.fast_shutdown | 1 | 1 | 1 |
Deze matrix is bewust pragmatisch, omdat echte projecten heel verschillend groeien. Ik begin met deze waarden en observeer vervolgens de hitrate, het gebruikte aandeel in het gedeelde geheugen en het optreden van evictions. Bij tekenen van druk verhoog ik eerst opcache.memory_consumption in gematigde stappen. Daarna pas ik opcache.max_accelerated_files aan totdat het aantal bestanden comfortabel past. Zo blijft de Cache effectief en aanvragen blijven gelijkmatig vlot.
Instellingen per omgeving: ontwikkeling, staging, productie
Bij de ontwikkeling is snelle feedback op codewijzigingen belangrijk, daarom stel ik validate_timestamps=1 en revalidate_freq zeer laag of zelfs op 0 in. Bij staging controleer ik de realistische belasting en stel ik het geheugen ruim in, zodat de resultaten dicht bij de latere live-werking liggen. In de productie verhoog ik de testfrequentie of schakel ik tijdstempels helemaal uit als mijn implementatie de cache daarna gericht leegmaakt. Voor CLI-gebaseerde workers activeer ik enable_cli=1, zodat terugkerende taken ook door de Bytecode-cache profiteren. Zo genereert elke omgeving precies het gedrag dat ik nodig heb, zonder verrassingen bij reactietijden.
Geavanceerde instellingen die vaak het verschil maken
Naast de basisparameters zijn er schakelaars waarmee ik de stabiliteit en veiligheid kan verhogen en bijwerkingen kan minimaliseren:
- opcache.max_wasted_percentage: Bepaalt vanaf welk fragmentatieniveau OPcache een interne herstructurering van het geheugen in gang zet. Bij sterk wisselende codebases verlaag ik de waarde iets om minder „versnipperd“ geheugen te hebben.
- opcache.force_restart_timeout: tijdsduur in seconden waarna OPcache een geforceerde herstart uitvoert als een herstart nodig is, maar er nog processen actief zijn. Dit voorkomt zeer lange onzekere situaties.
- opcache.file_update_protection: beschermingsvenster in seconden waarin recent gewijzigde bestanden niet onmiddellijk worden gecachet. Dit helpt tegen half geschreven bestanden tijdens implementaties of op netwerkschijven.
- opcache.restrict_api: Beperkt welke scripts opcache_reset() en statusfuncties mogen aanroepen. In productie stel ik dit strikt in, zodat alleen administratieve eindpunten toegang hebben.
- opcache.blacklist_filename: bestand waarin ik patronen bijhoud die worden uitgesloten van de cache (bijv. zeer dynamische generators). Dit bespaart ruimte voor meer kritieke scripts.
- opcache.validate_permission en opcache.validate_root: actief wanneer er meerdere gebruikers/chroots in het spel zijn. Zo voorkomt PHP dat gecachete code uit de ene context ongeoorloofd wordt gebruikt in een andere context.
- opcache.use_cwd en opcache.revalidate_path: controleert hoe OPcache scripts identificeert wanneer paden via verschillende werkdirectory's/symlinks worden geïntegreerd. Bij release-symlinks test ik deze waarden specifiek om dubbele caches te voorkomen.
- opcache.cache_id: Als meerdere virtuele hosts dezelfde SHM delen (zeldzaam), scheid ik de caches netjes via een unieke ID.
- opcache.optimization_level: Ik laat dit meestal op standaard staan. Alleen bij debugging-edgecases verminder ik tijdelijk de optimalisatiepasses.
Preloading: delen van de code permanent in het geheugen bewaren
Met PHP 7.4+ kan ik via opcache.preload en opcache.preload_user centrale framework- of projectbestanden laden en koppelen bij het opstarten van de server. Het voordeel: klassen zijn beschikbaar zonder autoload-hits en hot paths zijn direct beschikbaar. Een paar praktische regels:
- Preloading is vooral de moeite waard bij grote, stabiele codebases (bijv. Symfony, eigen kernbibliotheken). Bij WordPress gebruik ik het met mate, omdat Core/Plugins vaker worden bijgewerkt.
- Een preload-bestand bevat gerichte opcache_compile_file()-aanroepen of integreert een autoloader die gedefinieerde klassen van tevoren laadt.
- Elke codewijziging aan preload-relevante bestanden vereist een herstart van PHP-FPM, zodat de preload opnieuw wordt opgebouwd. Ik integreer dit in implementaties.
- Ik meet het effect apart: niet elke code profiteert hiervan; preloading verbruikt extra gedeeld geheugen.
JIT en OPcache: voordelen, beperkingen, geheugenvereisten
Sinds PHP 8 bestaat de Just-In-Time-Compiler (JIT), die via OPcache wordt aangestuurd (opcache.jit, opcache.jit_buffer_size). Voor typische webworkloads met I/O- en databasebelasting levert JIT vaak weinig op. Bij code die veel CPU-belasting vereist (bijv. beeld-/gegevensverwerking) kan het merkbaar helpen. Ik ga als volgt te werk:
- Ik activeer JIT conservatief en meet statistieken van echte gebruikers en CPU-profielen. Blind activeren vergroot de geheugenbehoefte en kan edgecases veroorzaken.
- Ik dimensionneer de JIT-buffer afhankelijk van CPU-intensieve routes. Te kleine buffers bieden geen meerwaarde, te grote buffers verdringen bytecode.
- Als de hitrate of SHM-bezetting eronder lijdt, geef ik OPcache voorrang boven JIT. Bytecode-cache is voor de meeste sites de belangrijkste hefboom.
Bestandspaden, symlinks en veilige implementatiestrategieën
OPcache is padgebaseerd. Daarom leg ik de nadruk op de implementatiestrategie:
- Atomic Releases via symlink (bijv. /releases/123 -> /current): netjes, maar let op opcache.use_cwd en realpath-gedrag. Ik vermijd dubbele caches door ervoor te zorgen dat alle workers consistent hetzelfde echte pad zien.
- Met validate_timestamps=0 moet de cache overal worden geleegd: na het omschakelen flush ik OPcache gericht op alle hosts/pods en rol ik PHP-FPM gecontroleerd opnieuw uit.
- Ik stem realpath_cache_size en realpath_cache_ttl af op OPcache, zodat bestandslookups snel en stabiel blijven.
- Op netwerkschijven (NFS/SMB) verhoog ik file_update_protection en ontwerp ik implementaties zodanig dat bestanden atomair worden vervangen.
Voor zeer snelle herstarts gebruik ik vaak een tweestapsprocedure: eerst opwarmen op de achtergrond, daarna een korte, gecoördineerde herlaadbeurt van alle workers, zodat het eerste liveverkeer al een warme cache aantreft.
Bestandcache, opwarmen en priming
Naast het gedeelde geheugen kan OPcache bytecode optioneel naar de schijf schrijven (opcache.file_cache). Dit helpt in speciale scenario's:
- In containeromgevingen kan een bestandscache tussen FPM-herstarts Verkort de recompilatietijden, mits de opslag snel is.
- Ik gebruik opcache.file_cache voorzichtig: op trage of gedistribueerde bestandssystemen levert het weinig op en verhoogt het de complexiteit.
- opcache.file_cache_only is een speciaal geval voor omgevingen zonder SHM – niet gebruikelijk voor prestatiegerichte opstellingen.
Voor warming-ups maak ik kleine „primers“:
- Een CLI-script roept opcache_compile_file() aan voor hot files, bijvoorbeeld autoloaders, centrale frameworkklassen, grote helpers.
- Een crawler bezoekt de belangrijkste routes (startpagina, login, checkout) zodat de bytecode en de downstream-caches op tijd warm zijn.
- Ik plan de opwarmingen zo dat ze kort voor het overschakelen van de versie klaar zijn.
OPcache in de stack: PHP-FPM, objectcache en paginacache
OPcache laat vooral zijn kracht zien in combinatie met PHP-FPM, een nette procesconfiguratie en extra cache-lagen. Bij WordPress combineer ik het met een objectcache (zoals Redis) en een paginacache, zodat de database en rendering worden ontlast. Daarbij let ik op de Single-thread-prestaties, omdat PHP-verzoeken sterk afhankelijk zijn van afzonderlijke CPU-kernen. Als er toch druk ontstaat, verdeel ik de belasting over PHP-FPM-workers, zonder het gedeelde geheugen van OPcache te klein te kiezen. Zo gebruik ik de Stapel volledig, in plaats van alleen aan één stelschroef te draaien.
Frequente fouten en snelle controles
Een te kleine cache leidt tot evictions, die ik kan herkennen in de OPcache-status of phpinfo(). Als dat gebeurt, verhoog ik stapsgewijs opcache.memory_consumption en controleer ik het effect via de hitrate. Als bestanden niet sneller worden, stel ik opcache.max_accelerated_files hoger in dan de werkelijke hoeveelheid bestanden in het project. Bij implementatieproblemen controleer ik validate_timestamps: met 0 blijft oude bytecode actief totdat ik de cache expliciet leegmaak. Tools zoals Doctrine vereisen DocBlocks, daarom laat ik save_comments=1 staan om Fout door het ontbreken van annotaties te vermijden.
OPcache controleren en interpreteren
Ik meet de hitrate en streef naar waarden die dicht bij 100 procent liggen, zodat verzoeken bijna altijd vanuit de cache worden gestart. Daarnaast houd ik het geheugengebruik en het aantal evictions in de gaten om knelpunten vroegtijdig te herkennen. Met opcache_get_status() maak ik kleine dashboards of voer ik bestaande monitoringoplossingen in. Zo zie ik veranderingen na releases of plugin-updates direct in de trend. Met deze statistieken neem ik weloverwogen beslissingen. Beslissingen en pas alleen aan wat echt nodig is.
Concrete richtlijnen die hun waarde hebben bewezen:
- Hitrate > 99 % onder normale en piekbelasting; daaronder controleer ik de bestandsverdeling en warm-up.
- Vrij SHM-aandeel constant > 5–10 %; anders schaal ik het geheugen.
- Evictions in de loop van de tijd: eenmalige pieken na implementatie zijn oké; voortdurende evictions duiden op onderdimensionering of sterke fragmentatie.
- Wasted Memory in de gaten houden: als het de limiet bereikt, plan ik een gecontroleerde OPcache-herbouw (bijvoorbeeld tijdens onderhoudsvensters).
Voorbeeld: WordPress-installatie met veel verkeer
Voor grote WordPress-websites kies ik opcache.enable=1 en opcache.enable_cli=1, zodat ook CLI-workers hiervan profiteren. Ik stel het gedeelde geheugen graag in op 384 MB of hoger als er veel plug-ins en een thema met veel functies bij betrokken zijn. Ik verhoog opcache.interned_strings_buffer naar 64 MB, omdat veel klasse- en functienamen in alle verzoeken terugkomen. Voor extreem performante omgevingen stel ik validate_timestamps=0 en revalidate_freq=0 in, maar flush ik de cache direct na elke release. Het blijft belangrijk om implementaties zo te ontwerpen dat er geen oude bytecode in omloop blijft.
Praktische workflow voor tuning en implementaties
Ik werk in vaste cycli: meten, wijzigen, controleren. Eerst beveilig ik statuswaarden zoals hitrate, bezetting en evictions, daarna pas ik een parameter aan en meet ik opnieuw. Voorafgaand aan een release wis ik bij gedeactiveerde tijdstempels gericht de OPcache, hetzij via een herstart van PHP-FPM, hetzij via een klein script. Vervolgens controleer ik piekbelastingen met echt verkeer of representatieve benchmarks. Als er opvallend gedrag optreedt, controleer ik ook Geheugenfragmentatie, omdat ze de bruikbare Gedeelde Het geheugen vermindert.
Een paar extra routines die hun nut hebben bewezen in teams:
- Versiebeheer voor parameterwijzigingen: opcache.ini in de repo, wijzigingen via pull request en changelog.
- Canary-implementaties: eerst laadt slechts een deel van de workers/pods nieuwe versies en bouwt een cache op, daarna volgt de uitrol naar alle instanties.
- Noodschakelaar: een intern admin-eindpunt met beveiligde toegang dat opcache_reset() en gerichte opcache_invalidate()-aanroepen toestaat – in combinatie met opcache.restrict_api.
- Grootte schatten: Als vuistregel reken ik in eerste instantie 1-2 MB OPcache per 100-200 PHP-bestanden en pas ik dit vervolgens aan op basis van de werkelijke statistieken. Voor WordPress met veel plug-ins voeg ik een buffer toe.
Kort samengevat
OPcache versnelt PHP-toepassingen door de gecompileerde bytecode in het RAM-geheugen opslaat. Met de juiste instellingen voor geheugen, aantal bestanden en tijdstempelstrategie bereikt u constant korte responstijden. Zorg ervoor dat u afstemt met PHP-FPM en andere cache-lagen, zodat de hele stack goed samenwerkt. Controleer de hitrate, bezetting en evictions, zodat u gerichte aanpassingen kunt doen. Zo bent u verzekerd van een krachtige, betrouwbare Platform voor hoge belasting en groei.


