...

PHP Realpath Cache: een onderschatte boost voor de prestaties van PHP

De vaak over het hoofd geziene manier om PHP-verzoeken te versnellen heet PHP Realpath Cache: deze slaat opgeloste paden op in het werkgeheugen en vermindert het aantal kostbare bestandssysteemquery’s bij `include/require`. In projecten met Symfony, Laravel of een grote WordPress-installatie verbeter ik met een nette Realpath-configuratie de Prestaties meetbaar en houd het aantal systeemaanroepen per verzoek aanzienlijk lager.

Centrale punten

  • Eenvoudiger Hebel: Realpath slaat padoplossingen op en vermindert het aantal toegangen tot het bestandssysteem.
  • Per werknemer: Elk PHP-FPM-proces beheert zijn eigen Realpath-cache.
  • Maat Belangrijk: een te kleine cache leidt tot thrashing en vertraagt verzoeken.
  • TTL bepaalt de actualiteit: lange TTL voor stabiele implementaties, korte TTL voor symlinks/geheime gegevens.
  • Controle: realpath_cache_get()/size() geven de bezettingsgraad en de vrije ruimte weer.

Wat de Realpath-cache precies doet

Bij elke `include`, `require` of `file_get_contents` zet PHP relatieve paden om in absolute paden en slaat deze resultaten op in het Cache. Als hetzelfde pad opnieuw binnenkomt, lees ik het resultaat uit het geheugen en bespaar ik mezelf de kostbare gang naar de bestandssysteem. Dit mechanisme vermindert het aantal systeemaanroepen aanzienlijk, vooral wanneer Composer via autoloading veel klassen en configuratiebestanden laadt. Belangrijk: de Realpath-cache bestaat per proces, waardoor elke PHP-FPM-worker pas na enkele verzoeken profiteert, wanneer hij zijn eigen cache heeft opgebouwd. Zo ontstaat een continu versnellend effect, dat zich bij een hoge belasting bijzonder goed uitbetaalt.

Waarom de cache in grote frameworks belangrijk is

Grote frameworks en veel plug-ins genereren per verzoek ontelbare Toegang tot bestanden, die zonder caching elke keer opnieuw de paden zouden moeten omzetten. Als de Realpath-cache te klein is, worden oudere vermeldingen eruit verdrongen, komen er nieuwe bij, en zie ik pure Ronkend. Dit leidt tot herhaalde stat- en lookup-bewerkingen, die tijd kosten en de I/O belasten. In de praktijk kan hiermee het aantal systeemaanroepen per verzoek met ongeveer 5–15 % worden verlaagd, wat bij een hoge verzoekfrequentie een enorm verschil maakt. Hoe modulaire de toepassing is, hoe groter het hefboomeffect via een goed gedimensioneerde Realpath-cache.

Zo bepaal ik de juiste cachegrootte

Ik tel eerst het aantal unieke paden van een typisch verzoek, schat de gemiddelde padlengte en tel per vermelding ongeveer 128 bytes bij Overhead. Op basis van het aantal, de padlengte en de overhead bereken ik een realpath_cache_size die voldoende Buffer biedt. Veel grotere projecten komen uit op een grootte tussen de 4 en 16 MiB, zeer omvangrijke monorepos zelfs nog meer. Het is belangrijk dat de cache niet tegen de limiet aan zit, anders verlies ik het voordeel doordat ik hem voortdurend moet leegmaken. Ik verhoog de limiet stapsgewijs, houd de bezetting in de gaten en pas deze vervolgens aan.

Aanbevolen instellingen en voorbeeldwaarden

Standaardwaarden stammen uit de tijd dat codebases nog klein waren en sluiten vaak niet meer aan bij de huidige situatie Opstellingen. Voor veel productieve toepassingen stel ik realpath_cache_size in op 4096K tot 16384K en verleng ik realpath_cache_ttl tot 360–600 Seconden of meer. De projectomvang, de frequentie van de implementaties en de aard van het bestandssysteem zijn bepalend. De onderstaande tabel geeft zinvolle richtwaarden ter oriëntatie en helpt bij het opstarten van de tuning. Vervolgens pas ik de cijfers aan op basis van monitoring en belastingstests.

Instelling Herhaaldelijke wanbetaling Goede startwaarden Verwacht effect
realpath_cache_grootte 4096K (4 MiB) 4096K–16384K Verminderd Ronkend bij veel bestanden
realpath_cache_ttl 120–600 s 360–900 s Langere Cache-stop, minder herhaalde ontbindingen

Voorbeelden in het php.ini-bestand: realpath_cache_size = 4096K en voor grote frameworks realpath_cache_size = 16384K. Voor de levensduur gebruik ik vaak realpath_cache_ttl = 360 of hoger bij zeldzame releases. Zo blijven paden gedurende vele verzoeken in het geheugen opgeslagen, zonder voortdurend opnieuw te worden gevalideerd.

Kies TTL verstandig – afhankelijk van de implementatie

De juiste TTL hangt sterk af van het implementatieproces en het gebruik van Symlinks . Wanneer ik van release wissel via symlink-rotatie, mag de cache geen verouderde paden weergeven; daarom stel ik de TTL kort in of start ik FPM opnieuw op na de Uitrol. In Kubernetes-omgevingen waar Secrets of ConfigMaps als volumes worden gebruikt, verkort ik de TTL aanzienlijk of schakel ik de Realpath-cache tijdelijk uit. In meer statische webhostingsituaties zijn langere TTL’s daarentegen gunstig, omdat paden zelden veranderen. Zo zorg ik voor een evenwicht tussen actualiteit en snelheid, afgestemd op de omgeving.

Controleren en verifiëren

Ik controleer regelmatig met realpath_cache_get(), welke paden in de Cache liggen, en met realpath_cache_size(), hoeveel opslagruimte daarvan in beslag wordt genomen. Als het gebruik dicht bij de geconfigureerde grootte ligt, verhoog ik de Capaciteit Stap voor stap. Als de cache extreem snel vol raakt, zie ik dat als een teken dat er meer geheugen nodig is of dat de TTL te kort is. Na grotere plugin-installaties of framework-updates controleer ik het opnieuw. Alleen wie de cijfers kent, kan zinvolle beslissingen nemen over het optimaliseren van de site.

Meetbaar effect: zo meet ik systeemaanroepen en latenties

Om ervoor te zorgen dat de tuning betrouwbaar is, voer ik metingen uit voor en na de wijzigingen. Op Linux registreer ik bestandssysteem-aanroepen per verzoek met strace of perf, naar keuze op een afzonderlijke FPM-worker of via de CLI.

  • Enkelvoudig verzoek (CLI): strace -c -o /tmp/strace.txt php public/index.php geeft een overzicht van hoeveel stat(), openat() en lstat() ontstaan.
  • FPM-Worker toevoegen: strace -fp -e trace=file -o /tmp/strace-fpm.log toont alleen bestandsgerelateerde oproepen. Voorheen met ps het PID van de worker achterhalen.
  • Belastingstest: Met tools zoals van of simuleer ik een belasting en vergelijk ik de P95/P99-latenties bij verschillende cachegroottes.

Tegelijkertijd laat ik de cachebezetting vanuit PHP weergeven, bijvoorbeeld in een debug-endpoint of via de CLI:

<?php
$entries = realpath_cache_get();
$size    = realpath_cache_size();
printf("Entries: %d, Used: %d bytes (%.2f MiB)\n", count($entries), $size, $size/1048576);

Zo kan ik zien of de verhoging van de realpath_cache_grootte waardoor het aantal fouten en bestandssysteemoproepen daadwerkelijk afneemt, in plaats van alleen maar RAM te bezetten. In het ideale geval stijgt de hitrate, terwijl de P95-latenties merkbaar dalen.

Zo verwarm ik de Realpath-cache gericht

Omdat de cache per worker wordt aangemaakt, is het de moeite waard om een Opwarming na de deploy of de herstart. Het doel is dat de meest voorkomende includes vroeg in de cache terechtkomen, voordat er echt gebruikersverkeer binnenkomt.

  • Verzoeken om herhalingen: Na de uitrol voer ik automatisch een aantal typische URL’s (frontend, admin, API) uit.
  • CLI-priming: Een kort bootstrapping-script laadt centrale paden (autoloader, kernel, configuratie, routes).
<?php
// warmup.php
require __DIR__.'/vendor/autoload.php';  // Composer
require __DIR__.'/config/bootstrap.php'; // Afhankelijk van het project
require __DIR__.'/public/index.php';     // Front-controller (kan een korte run activeren)
echo sprintf("%d-vermeldingen voorbereid, %d bytes gebruikt\n",
    count(realpath_cache_get()), realpath_cache_size());

Deze warm-up dekt weliswaar niet alle daadwerkelijke verzoeken, maar legt de meest gebruikte paden vast en verkort de aanvankelijke koudstartfase per worker merkbaar.

Samenwerking met OPcache en de bestandssysteemcache

OPcache versnelt de uitvoering van PHP-bestanden, terwijl Realpath het pad naar het bestand verkort; daarom combineer ik beide Technieken. Voor de OPcache-instellingen gebruik ik beproefde waarden en verwijs ik naar gedegen OPcache-optimalisatie, zodat bytecode en paden optimaal op elkaar zijn afgestemd. Daarnaast profiteert Realpath van een ‘warme’ OS-cache, die snel directory-lookups en metadata levert. Zo voorkom ik dubbele wachttijden bij het laden en het parseren. Wie beide niveaus op elkaar afstemt, realiseert merkbare verbeteringen in de responstijd.

Optimaal gebruikmaken van het automatisch laden van composers

De Composer-autoloader is een belangrijke motor voor het omzetten van paden. Hoe deterministischer deze werkt, hoe gemakkelijker het is voor de Realpath-cache.

  • Classmap optimaliseren: composer dump-autoload -o beperkt het aantal scans van mappen en herhaalde zoekopdrachten.
  • Zich strikt aan autoload houdenMet classmap-autoritatief (Projectomgeving) vermijd ik onnodige fallbacks die anders extra padresoluties zouden veroorzaken.
  • Structuur ordenen: Vlakke, consistente maphiërarchieën en weinig uitzonderingsgevallen (bijvoorbeeld module- of clientoverschrijdende includes) zorgen voor een stabiele cachebelasting.

Het resultaat: minder verschillende paden per verzoek, meer hergebruik in de Realpath-cache en dus lagere IO-kosten.

FPM en geheugenbudget: wat is realistisch per worker?

Omdat de Realpath-cache per proces bestaat, wordt de geconfigureerde grootte vermenigvuldigd met het aantal FPM-workers. Daarom stel ik een budget vast:

  • Voorbeeld: 12 workers × 8 MiB = 96 MiB Realpath-header; daar komen nog de OPcache, de PHP-heap en de overhead van de extensies bij.
  • In evenwicht brengen: Als OPcache voldoende ruimte heeft, kan Realpath enkele MiB extra krijgen – of andersom.
  • Specifiek voor zwembaden: Verschillende FPM-pools (Front, Admin, API) mogen verschillende Realpath-groottes hebben, afhankelijk van de respectieve code-footprint.

Naarmate de code bij elke release groeit, groeit ook de realpath_cache_grootte-behoefte gaat daar doorgaans mee gepaard. Daarom controleer ik regelmatig de piekbezetting onder belasting, niet alleen in ruststand.

Bijzondere gevallen: symbolische koppelingen, containers en NFS

Bij de uitrol van symlinks schrijf ik een korte TTL of start FPM opnieuw op na de deploy, zodat alle workers de nieuwe paden laden. In containers met veranderlijke volumes let ik erop dat de cache geen verouderde Doelen door de TTL aan te passen. Bij NFS wordt bovendien een goede OPcache-strategie en zo min mogelijk wisselingen van map aanbevolen. Als paden tijdens de uitvoering veranderen, maak ik in geval van twijfel gericht de cache leeg met clearstatcache(true) ook het Realpath-gedeelte. Duidelijke implementatieregels voorkomen inconsistente toestanden tussen de verschillende workers.

Typische struikelblokken en beperkingen

Omdat de cache per proces bestaat, moet elke Werknemer Allereerst moet je paden verzamelen voordat het effect van kracht wordt. In omgevingen met strenge open_basedir-beperkingen werkt de Realpath-cache beperkt, dus houd ik hier rekening mee Grenzen bij de planning. Te kleine caches leiden tot thrashing, te grote caches verspillen RAM – ik zoek met metingen het hoogtepunt van de curve. Bovendien houd ik er rekening mee dat Realpath geen cache voor metadata of inhoud is, maar uitsluitend padresoluties opslaat. Wie verkeerde verwachtingen heeft, ziet oorzaken elders over het hoofd.

Bedrijfszekerheid: veelvoorkomende storingen en snelle controles

Sommige symptomen wijzen duidelijk op Realpath-problemen – en kunnen snel worden gecontroleerd:

  • Schommelende latenties na de implementatie: Ofwel een te lange TTL bij symlink-rotatie, ofwel een ontbrekende warm-up. Oplossing: korte TTL, FPM-herstart, gevolgd door priming.
  • Veel herhaalde stat()-weergavenMet strace zichtbaar; vaak is de cachegrootte te klein of verdringen bepaalde dynamische paden de ‘hot entries’.
  • Grote variatie tussen workers: Verschillende caches per proces. Oplossing: consistente opstartfase en gelijkmatige verdeling van verzoeken.

Een snelle gezondheidscontrole via PHP is vaak voldoende:

<?php
$entries = realpath_cache_get();
$byDir = 0; $byFile = 0;
foreach ($entries as $e) { $e['is_dir'] ? $byDir++ : $byFile++; }
printf("Mappen: %d, Bestanden: %d, Gebruikt: %.2f MiB\n", $byDir, $byFile, realpath_cache_size()/1048576);

Zo kan ik zien of vooral mappen (veel modules, vendorstructuren) of bestanden (talrijke configuratiebestanden/klassen) de cache domineren – en pas ik de structuur of de grootte aan.

Stat-cache versus Realpath-cache: bewust onderscheid maken

PHP beheert naast de Realpath-cache ook een Stat-Cache voor resultaten van stat() en aanverwante oproepen. Beide caches kunnen worden gebruikt met clearstatcache() beïnvloeden:

  • clearstatcache() maakt de Stat-cache leeg (optioneel voor een specifiek bestand).
  • clearstatcache(true) maakt bovendien de Realpath-cache leeg.

In zeldzame gevallen – bijvoorbeeld bij langlopende CLI-workers met dynamische mounts of bij hot-swaps – maak ik gebruik van een gerichte clearstatcache(true)-Hook na bekende wijzigingen. Anders laat ik de TTL zijn werk doen en vermijd ik onnodige ongeldigverklaringen.

Praktijktest voor hostingomgevingen

Ik bepaal eerst de omvang van het project, dat wil zeggen hoeveel bestanden een typisch verzoek laadt, en controleer daarna de belasting van de Caches. Vervolgens kies ik een `realpath_cache_size` die alle veelgebruikte paden plus een reserve omvat, en stel ik een TTL in die aansluit bij de deploy-frequentie. Daarna houd ik de effecten in de gaten via monitoring en logs en pas ik de waarden voorzichtig aan, in plaats van ze grofweg te verhogen. Daarnaast is het de moeite waard om de OS-cache te bekijken, bijvoorbeeld de Linux-instelling VFS-cache-druk, omdat Realpath profiteert van snelle directory-lookups. Zo breng ik verbeteringen aan zonder bijwerkingen over het hoofd te zien.

Toepassingsgebied en configuratiemogelijkheden: waar ik welke waarde instel

Afhankelijk van de omgeving pas ik de parameters op verschillende plaatsen aan:

  • Wereldwijd: php.ini voor systeembrede standaardinstellingen.
  • Pro-Pool: In FPM-pools per php_admin_value[realpath_cache_size] en php_admin_value[realpath_cache_ttl] specifiek voor frontend/API verschillend dimensioneren.
  • Pro-map: In .user.ini (indien toegestaan), handig in shared hosting-omgevingen.

Belangrijk: wijzigingen aan de php.ini en FPM-poolconfiguraties moeten opnieuw worden opgestart of herladen, zodat de workers met de nieuwe waarden starten.

CLI, queue-workers en cronjobs: dezelfde regels, andere uitvoeringstijden

CLI-scripts en queue-workers profiteren ook van de Realpath-cache – maar de Levensduur vaak anders:

  • Tijdelijke CLI-taken: Bij elke aanroep wordt de cache opnieuw aangemaakt. In dit geval hebben warm-up en een lange TTL weinig zin; het is belangrijker dat de cache groot genoeg is, zodat herhaalde includes in de job zelf in de cache worden opgeslagen.
  • Daemons/Workers: Langlopende processen (Supervisor, Systemd) bouwen een stabiele cache op. Na een Code vernieuwen (Deploy) moet het proces opnieuw starten, anders kunnen er verouderde paden in de cache achterblijven.

Projectomvang inschatten en opslagcapaciteit

Een toepassing met 4000 unieke paden en een padlengte van 80 bytes plus 128 bytes overhead per vermelding neemt ruwweg 832 KB in beslag Geheugen in de Realpath-cache; ik reken op 4 MiB of meer, met wat speling. Als de codebasis door plug-ins of modules aanzienlijk groeit, schaal ik lineair mee en controleer ik opnieuw de Hits versus fouten. Op shared-hosts let ik bovendien op inode-limieten, omdat te veel kleine bestanden het hele systeem belasten; dit overzicht helpt me daarbij om Inodes-limieten. Het is beter om wat speling in te bouwen dan voortdurend op het uiterste te werken. Zo bespaar ik systeemoproepen zonder onnodig RAM-gebruik.

Kort en bondig: mijn tuningplan

Ik meet eerst het aantal bestanden per verzoek, daarna stel ik een passende Cachegrootte en een die aansluit bij de implementatiepraktijk TTL. Vervolgens controleer ik met realpath_cache_get()/size() de belasting, pas ik deze stapsgewijs aan en combineer ik dit alles met fijnafstemming van OPcache en de OS-cache. Bij de uitrol van symlinks houd ik de TTL kort of start ik FPM opnieuw op; in statische omgevingen gebruik ik lange TTL-waarden. Het doel blijft een hoge cache-hitrate zonder verspilling van RAM. Zo haal ik uit de Realpath-cache een onderschatte boost voor consistente PHP-prestaties.

Huidige artikelen

Server met gevisualiseerd PHP Opcache-geheugen voor fragmentatieanalyse
Administratie

Fragmentatie in PHP Opcache herkennen en verhelpen voor maximale prestaties

Leer hoe je PHP OPcache-fragmentatie kunt herkennen, deze kunt verhelpen door middel van monitoring en configuratie, en de prestaties van je applicaties kunt optimaliseren met gerichte PHP-tuning. Focus: PHP OPcache-fragmentatie in professionele hostingomgevingen.

Visualisatie van een Redis-cache met servers en gegevensstromen ter illustratie van LFU- en LRU-eviction-beleidsregels
Databases

Redis LFU versus LRU: welk verwijderingsbeleid is het juiste?

Om je cache optimaal te configureren, is het belangrijk dat je begrijpt hoe Redis-eviction met Redis LFU en Redis LRU werkt – dit artikel geeft je een directe vergelijking en helpt je bij het kiezen van het juiste beleid.