Wat hoge CPU-belasting betekent voor een WordPress-site

Hoge CPU-belasting betekent dat de server het grootste deel van zijn processortijd kwijt is aan PHP, MySQL en de overige processen die je WordPress-site draaiende houden. Dit artikel legt uit wat CPU-gebruik nou eigenlijk meet, waarom een dichtgetrokken CPU juist die symptomen geeft die je ziet, en welke aangrenzende problemen mensen er steevast mee verwarren.

CPU-belasting is het deel van de processortijd dat de server bezig is met code die voor jouw site draait. Op een WordPress-server is die code vooral PHP (WordPress core, plugins en thema's), MySQL of MariaDB (queries op de database) en de webserver zelf (nginx of Apache). Zodra dat aandeel tegen het plafond aan zit, halen verzoeken hun normale tijd niet meer en komen de symptomen die je ziet uit het wachten in de rij, niet uit één duidelijk kapot ding.

Wat CPU-gebruik eigenlijk meet

Het getal dat je in een hostingpaneel ziet onder "CPU-gebruik" is bijna altijd één van twee dingen, en die twee zijn niet hetzelfde.

Het eerste is gebruik per core, in procenten. Een server met 4 cores heeft 400% CPU beschikbaar over alle cores samen. Een WordPress pagina-opbouw die één core volledig op 100% trekt, gebruikt nog maar een kwart van de machine. Als een tool als htop één regel op 100% laat zien en de rest op nul, dan is dat één verzadigde core, niet de hele server. De Linux top(1) man page beschrijft de kolommen en wat ze betekenen: %Cpu(s) splitst het totaal op in us (user code, zoals PHP), sy (kernel code), wa (wachten op disk I/O) en een paar andere. De meeste WordPress CPU-druk zit in us. Een hoge wa betekent dat de echte bottleneck de schijf is, niet de CPU.

Het tweede is load average, de drie getallen (gemiddeld over 1, 5 en 15 minuten) die je bovenin uptime of top ziet staan. De Linux kernel beschrijft load average als het gemiddelde aantal taken dat runnable is of in uninterruptible sleep zit over dat venster. Load average is geen percentage. Een load van 4.0 op een machine met 4 cores betekent ruwweg "alle CPU's zijn vol bezet, zonder rij". Een load van 8.0 op diezelfde machine betekent dat er ongeveer evenveel taken staan te wachten als er draaien. Vuistregel: deel de load door het aantal cores en je hebt een ruwe utilisatie. Boven de 1.0 per core zit je structureel in de knel.

Hostingpanelen tonen meestal één van die twee getallen en noemen beide gewoon "CPU". Weten welke je voor je hebt, is de eerste stap naar interpreteren wat het zegt.

Waarom een dichte CPU trage pagina's geeft, geen errors

Hostingpakketten hebben een CPU-limiet. Op een virtuele machine zet de hypervisor een vast aantal vCPU's. Op shared hosting trekt CFS (de Linux Completely Fair Scheduler) of een cgroup-limiet een dak boven het percentage van een core dat één account mag verstoken. Op managed WordPress-platforms zit de cap meestal in een quota van CPU-seconden per minuut. Die cap is er omdat één losgeslagen site nooit alle andere sites op dezelfde machine mag uithongeren.

Als een WordPress-verzoek CPU nodig heeft en die is er niet, geeft de kernel geen foutmelding terug. Het proces gaat in de wachtrij. Het verzoek draait wel, alleen later. Voor de bezoeker betekent dat: de pagina doet er langer over om te starten, langer om opgebouwd te worden en langer om verstuurd te worden. Voor de server betekent het dat elke actieve PHP-FPM worker zit te wachten tot hij aan de beurt is. Die wachtrij is precies wat de stijgende TTFB oplevert die de meeste monitoringsystemen als eerste opvangen. Wordt de wachtrij lang genoeg, dan loopt het verzoek over de configureerde timeout heen, geeft de webserver het op richting de upstream en ziet de bezoeker een 502 of 504. Als één PHP-script in zijn eentje lang genoeg CPU verstookt, trekt PHP zelf de stekker eruit op max_execution_time.

De keuze om te falen door wachten in plaats van door errors is bewust. Een wachtrij is herstelbaar. Zodra de piek voorbij is, loopt de rij vanzelf leeg en herstelt de site zich. Het alternatief, verzoeken weigeren zodra de CPU druk is, zou elke kleine verkeersgolf in een storing veranderen.

Wat dat betekent voor een WordPress-site in de praktijk

De CPU is eindig en de dingen die hem op een WordPress-server opmaken, vallen in een handvol bakjes.

Niet-gecachete PHP-verzoeken. Alles wat WordPress door PHP heen jaagt. Pagina's die uit een full-page cache komen (Varnish, nginx fastcgi_cache, een LSCache of WP Rocket disk cache) raken PHP helemaal niet en kosten bijna geen CPU. De CPU-druk op een WordPress-site komt van het kleine deel verzoeken dat echt PHP nodig heeft: ingelogde gebruikers, het WordPress-dashboard, WooCommerce winkelmandje en checkout, REST API-calls en al het persoonlijke output dat niet te cachen is. Brute-force-bescherming dekt de mitigatie voor bot-verkeer dat CPU uitput. Een site die 95% van het verkeer uit cache serveert, kan toe met een klein CPU-budget. Een site waar elke pagina dynamisch is, niet.

WP-Cron loops. WordPress draait geplande taken via wp-cron.php, standaard getriggerd door bezoekersverkeer. Plant een plugin een taak die faalt en zichzelf opnieuw inschrijft, dan loopt die loop bij elke pageload mee. Dat zie je terug als een lage maar constante CPU-vloer die niet matcht met het verkeer, en als geplande events die nooit verdwijnen uit wp cron event list.

Trage plugin admin-pagina's. Een plugin admin-scherm dat een N+1 database query draait (één query per regel, keer honderden regels) verstookt CPU aan de databasekant en aan de PHP-kant tegelijk. Dit is een hele bekende reden dat het WordPress-dashboard traag aanvoelt terwijl de voorkant gewoon werkt.

Achtergrondscans midden op de dag. Een backupplugin of security scanner die de hele wp-content/uploads map doorloopt en elke file hasht (zie ook de WordPress Heartbeat API voor admin-ajax.php CPU-druk), kost continu CPU zolang de scan loopt. Staat de scan op elk uur, dan komt de CPU-vloer er niet meer onder.

Taxonomy- en termoperaties op grote sites. Sites met tienduizenden termen (grote WooCommerce-catalogi, nieuwssites met dichte tag-taxonomieën) kunnen flink wat CPU kwijt zijn aan term-count herberekeningen, term-meta queries en database queries die meeschalen met het aantal termen. Het WordPress.org performance handbook beschrijft de veel voorkomende dure querypatronen die hier onder vallen.

Brute-force en bot-verkeer. Bots die /wp-login.php blijven hameren of die elke pagina van de site scrapen, eten PHP workers en CPU op verzoeken die nul echte waarde opleveren. De beste afvangst zit vóór PHP (rate limiting aan de edge, fail2ban op de auth log), want filteren binnen WordPress kost het verzoek nog steeds.

Wat hoge CPU NIET is

De meeste verwarring rond "hoge CPU" komt doordat mensen het gelijkstellen aan aangrenzende problemen die er ongeveer hetzelfde uitzien maar een andere oplossing vragen. Weten welke je echt hebt, is het verschil tussen een fix die werkt en een weekend dat je kwijt bent.

  • Niet hoge RAM. CPU en geheugen zijn aparte budgetten. Een site kan op 10% CPU draaien en alsnog door zijn RAM heen schieten (PHP loopt dan tegen zijn memory limit aan, of de OOM killer van de kernel begint processen om te leggen). Een site kan ook op 100% CPU zitten met geheugen zat. De ene voor de andere aanzien levert upgrades op die niets veranderen.
  • Niet hoge disk I/O. Als de bottleneck de schijf is, zitten processen in wa (I/O wait). De CPU wordt in sommige panelen als "druk" weergegeven, maar de cores rekenen niet, ze staan stil te wachten op de schijf. vmstat 1 maakt het verschil zichtbaar: hoge us/sy is echte CPU-druk, hoge wa is schijfdruk in een CPU-jasje. De vmstat man page legt de kolommen uit.
  • Niet hoge TTFB. TTFB is het symptoom, hoge CPU is één van de mogelijke oorzaken. Een site kan een hoge TTFB hebben omdat de database traag is, omdat een externe API-call binnen het PHP-verzoek traag is, of omdat PHP-FPM verzoeken in de rij zet. "Hoge CPU" en "hoge TTFB" als hetzelfde behandelen, leidt ertoe dat je de verkeerde laag aanpakt.
  • Niet hoge bezoekersaantallen. Een verkeerspiek op een goed gecachete site raakt de CPU nauwelijks, want de cache vangt het op. Een handvol ingelogde gebruikers op een site zonder cache kan de CPU minutenlang vastpinnen. De metric die met CPU correleert, is niet-gecachete PHP-verzoeken per seconde, niet ruwe bezoekersaantallen.
  • Niet een tekort aan workers. Uitgeputte PHP workers en hoge CPU komen vaak samen voor, maar het zijn andere faalmodes. Workers kunnen op zijn terwijl de CPU grotendeels niets doet (elke worker staat te wachten op een trage database query). De CPU kan vol zitten zonder dat workers op zijn (een klein aantal workers dat allemaal echt CPU-werk doet). Workers bijzetten op een site die CPU-gebonden is, maakt het juist erger, want elke nieuwe worker vecht om dezelfde schaarse CPU.

Waar je hierna terecht kunt

Voelt het meer als een traag-zijn in het algemeen dan als een duidelijk CPU-probleem? Dan loopt het algemene "WordPress site is traag" artikel door hoe je de juiste laag identificeert. Zit de pijn vooral in wp-admin? Dan legt het artikel over een trage WordPress admin uit waarom het dashboard als eerste op zijn limiet loopt. Laat je monitoring eerder wachtrijen zien dan ruwe CPU-druk? Dan staat het worker pool model dat dat veroorzaakt in het artikel over PHP workers.

Klaar met terugkerende traagheid?

Traagheid komt vaak terug na snelle fixes. Professioneel onderhoud houdt updates, caching en limieten consequent op orde.

Bekijk WordPress onderhoud

Doorzoek deze site

Begin met typen om te zoeken, of blader door de kennisbank en blog.