Leer Brendan Gregg’s praktische methoden (USE, RED, flame graphs) om latentie en productieknelpunten te onderzoeken met data, niet met giswerk.

Brendan Gregg is een van de meest invloedrijke stemmen op het gebied van systeemprestaties, vooral in de Linux-wereld. Hij heeft veelgebruikte boeken geschreven, praktische tooling gebouwd en—het belangrijkste—duidelijke methoden gedeeld om echte productieproblemen te onderzoeken. Teams passen zijn aanpak toe omdat het werkt onder druk: wanneer latentie piekt en iedereen antwoorden wil, heb je een manier nodig om van “misschien is het X” naar “het is zeker Y” te gaan met zo min mogelijk drama.
Een prestatiemethodologie is geen enkele tool of slimme opdracht. Het is een herhaalbare manier van onderzoeken: een checklist voor wat je eerst moet bekijken, hoe je ziet wat je ziet en hoe je beslist wat je daarna doet.
Die herhaalbaarheid is wat gokwerk reduceert. In plaats van te vertrouwen op degene met de meeste intuïtie (of de luidste mening), volg je een consistent proces dat:
Veel latentieonderzoeken lopen al mis in de eerste vijf minuten. Mensen springen meteen naar fixes: “voeg CPU toe,” “herstart de service,” “vergroot de cache,” “tune de GC,” “het moet het netwerk zijn.” Soms helpt dat—maar vaak verdoezelt het het signaal, verspil je tijd of introduceer je nieuw risico.
Gregg’s methoden dwingen je om “oplossingen” uit te stellen totdat je eenvoudigere vragen kunt beantwoorden: Wat is verzadigd? Wat geeft fouten? Wat is langzamer geworden—throughput, wachtrijen of individuele bewerkingen?
Deze gids helpt je de scope te beperken, de juiste signalen te meten en de bottleneck te bevestigen voordat je optimaliseert. Het doel is een gestructureerde workflow voor het onderzoeken van latentie- en profileringproblemen in productie, zodat resultaten niet van geluk afhangen.
Latentie is een symptoom: gebruikers wachten langer tot werk klaar is. De oorzaak ligt meestal ergens anders—CPU-contentie, disk- of netwerkwachten, lock-contentie, garbage collection, wachtrijen of vertraging bij externe afhankelijkheden. Alleen latentie meten vertelt je dat er pijn is, niet waar die vandaan komt.
Deze drie signalen zijn gekoppeld:
Voordat je gaat tunen, leg alle drie vast voor hetzelfde tijdsvenster. Anders “los” je latentie mogelijk op door werk te laten vallen of sneller te falen.
Gemiddelde latentie verbergt pieken die gebruikers onthouden. Een service met 50 ms gemiddeld kan nog steeds frequente stalls van 2 s hebben.
Houd percentielen bij:
Kijk ook naar de vorm van de latentie: een stabiele p50 met een stijgende p99 wijst vaak op intermitterende stalls (bijv. lock-contentie, I/O-hiccups, stop-the-world pauzes) in plaats van een algemene vertraging.
Een latentiebudget is een eenvoudige rekenoefening: “Als het verzoek binnen 300 ms klaar moet zijn, hoe kan die tijd worden verdeeld?” Deel het op in buckets zoals:
Dit budget kadert de eerste meettaak: identificeer welke bucket groeide tijdens de spike en onderzoek dat gebied in plaats van blind te tunen.
Latentiewerk ontspoort wanneer het “systeem is traag” wordt beschreven. Gregg’s methoden beginnen eerder: dwing de zaak in een specifieke, toetsbare vraag.
Schrijf twee zinnen op voordat je tools aanraakt:
Dit voorkomt dat je de verkeerde laag optimaliseert—zoals host-CPU—terwijl de pijn beperkt is tot één endpoint of één downstream afhankelijkheid.
Kies een venster dat past bij de klacht en, indien mogelijk, een “goed” vergelijkingsperiode bevat.
Scope je onderzoek expliciet:
Precies zijn hier maakt latere stappen (USE, RED, profilering) sneller omdat je weet welke data zou moeten veranderen als je hypothese klopt.
Noteer deploys, config-wijzigingen, traffic-shifts en infra-events—maar neem ze niet als gegeven aan. Formuleer ze als “Als X, dan zouden we Y verwachten,” zodat je snel kunt bevestigen of verwerpen.
Een klein log voorkomt dubbel werk tussen teamleden en maakt overdrachten soepeler.
Time | Question | Scope | Data checked | Result | Next step
Zelfs vijf regels zoals dit kunnen van een stressvol incident een herhaalbaar proces maken.
De USE-methode (Utilization, Saturation, Errors) is Gregg’s snelle checklist om de “grote vier” resources—CPU, geheugen, schijf (storage) en netwerk—te scannen, zodat je kunt stoppen met raden en beginnen met het versmallen van het probleem.
In plaats van naar tientallen dashboards te staren, stel je voor elke resource steeds dezelfde drie vragen:
Toegepast als routine wordt dit een snelle inventaris waar “druk” aanwezig is.
Voor CPU is utilization het percentage CPU-gebruik, saturation toont zich als run-queue pressure of threads die wachten om te draaien, en errors kunnen throttling (in containers) of slecht werkende interrupts zijn.
Voor geheugen is utilization gebruikt geheugen, saturation verschijnt vaak als paging of frequente garbage collection, en errors omvatten allocatiefouten of OOM-events.
Voor schijf is utilization device busy time, saturation is queue depth en lees/schrijf-wachttijd, en errors zijn I/O-fouten of timeouts.
Voor netwerk is utilization throughput, saturation drops/queues/latency, en errors retransmits, resets of packet loss.
Bij melding van traagheid zijn saturatiesignalen vaak het meest onthullend: wachtrijen, wachttijd en contentie correleren meestal directer met latentie dan ruwe utilization.
Service-metrics (zoals request-latentie en foutpercentage) vertellen je impact. USE vertelt je waar je vervolgens moet kijken door te identificeren welke resource onder druk staat.
Een praktische lus is:
De RED-methode houdt je verankerd aan gebruikerservaring voordat je in host-graphs duikt.
RED voorkomt dat je achter “interessante” systeemstatistieken aanholt die gebruikers niet raken. Het dwingt een kortere lus: welk endpoint is traag, voor welke gebruikers en sinds wanneer? Als Duration alleen op één route piekt terwijl CPU overall vlak is, heb je al een scherper startpunt.
Een nuttige gewoonte: houd RED uitgesplitst naar service en top-endpoints (of sleutel-RPC-methoden). Dat maakt het makkelijk om een brede degradatie te onderscheiden van een gelokaliseerde regressie.
RED vertelt je waar de pijn zit. USE helpt je te testen welke resource verantwoordelijk is.
Voorbeelden:
Houd de indeling gefocust:
Als je een consistente incident-workflow wilt, koppel dit dan aan de USE-inventaris zodat je sneller van “gebruikers voelen het” naar “deze resource is de beperking” komt zonder veel gedoe.
Een prestatieonderzoek kan binnen minuten in tientallen grafieken en hypothesen exploderen. Gregg’s denkwijze is om het smal te houden: jouw taak is niet om “meer data te verzamelen”, maar om de volgende vraag te stellen die het snelst onzekerheid wegneemt.
De meeste latentieproblemen worden gedomineerd door één kostenpost (of een klein paar): één hete lock, één trage afhankelijkheid, één overbelaste schijf, één GC-patroon. Prioriteren betekent eerst die dominante kost zoeken, want 5% knippen op vijf plekken verschuift zelden zichtbare latentie voor gebruikers.
Een praktische test: “Wat kan het grootste deel van de latentieverandering verklaren?” Als een hypothese slechts een klein deel kan verklaren, heeft het lagere prioriteit.
Gebruik top-down als je antwoordt op “Hebben gebruikers er last van?” Begin bij endpoints (RED-signalen): latentie, throughput, fouten. Dat helpt je voorkomen dat je iets optimaliseert dat niet op het kritieke pad ligt.
Gebruik bottom-up als de host duidelijk ziek is (USE-symptomen): CPU-saturatie, runaway geheugen, I/O-wacht. Als een node vastloopt, verspil je tijd met endpoint-percentielen zonder de beperking te begrijpen.
Wanneer een alert afgaat, kies een tak en blijf daarop totdat je het bevestigt of falsificeert:
Beperk jezelf tot een kleine set start-signalen en graaf pas door wanneer iets beweegt. Als je een checklist nodig hebt om focus te houden, koppel je stappen aan een runbook zodat elke nieuwe metric een doel heeft: het beantwoorden van een specifieke vraag.
Productieprofilering voelt riskant omdat het het live-systeem raakt—maar het is vaak de snelste manier om debat te vervangen door bewijs. Logs en dashboards vertellen je dat iets traag is. Profiling vertelt je waar tijd naartoe gaat: welke functies heet lopen, welke threads wachten en welke codepaden domineren tijdens het incident.
Profiling is een tool om tijd te budgetteren. In plaats van te discussiëren (“het is de database” vs “het is GC”), krijg je bewijs zoals “45% van CPU-samples zat in JSON-parsing” of “de meeste requests zijn geblokkeerd op een mutex.” Dat versmalt de volgende stap tot één of twee concrete fixes.
Elk beantwoordt een andere vraag. Hoge latentie met lage CPU wijst vaak naar off-CPU of lock-tijd in plaats van CPU-hotspots.
Veel teams beginnen met on-demand en schakelen naar always-on zodra ze de veiligheid vertrouwen en terugkerende issues zien.
Productieve veilige profiling draait om kostenbeheersing. Geef de voorkeur aan sampling (niet elk event traceren), houd capture-vensters kort (bijv. 10–30 seconden) en meet overhead eerst in een canary. Als je twijfelt, begin met lage samplefrequentie en verhoog alleen als het signaal te ruisig is.
Flame graphs visualiseren waar sampled tijd naartoe ging tijdens een profiling-venster. Elke “box” is een functie (of stack frame) en elke stack toont hoe uitvoering die functie bereikte. Ze zijn uitstekend om snel patronen te zien—maar ze zeggen niet automatisch “de bug zit hier.”
Een flame graph vertegenwoordigt meestal on-CPU samples: tijd dat het programma daadwerkelijk op een CPU-core draaide. Het kan CPU-intensieve codepaden, inefficiënte parsing, overmatige serialisatie of hotspots die echt CPU verbranden, aan het licht brengen.
Het toont niet direct wachten op schijf, netwerk, scheduler-delays of wachten op een mutex (dat is off-CPU tijd en vereist andere profiling). Het bewijst ook geen causaliteit voor gebruikerszichtbare latentie tenzij je het koppelt aan een afgebakend symptoom.
De breedste box is verleidelijk om te beschuldigen, maar vraag: is het een hotspot die je kunt veranderen, of gewoon “tijd besteed in malloc, GC of logging” omdat het echte probleem upstream ligt? Let ook op ontbrekende context (JIT, inlining, symbolen) die een box als schuldige kan doen lijken terwijl het slechts de boodschapper is.
Behandel een flame graph als antwoord op een afgebakende vraag: welk endpoint, welk tijdvenster, welke hosts en wat veranderde. Vergelijk “voor vs na” (of “gezond vs gedegradeerd”) flame graphs voor hetzelfde request-pad om profiling-ruis te vermijden.
Wanneer latentie piekt, kijken veel teams eerst naar CPU%. Dat is begrijpelijk—maar vaak wijst het in de verkeerde richting. Een service kan “maar 20% CPU” gebruiken en toch pijnlijk traag zijn als threads het grootste deel van hun tijd niet draaien.
CPU% beantwoordt “hoe druk is de processor?” Het beantwoordt niet “waaraan ging de tijd van mijn verzoek op?” Verzoeken kunnen stagneren terwijl threads wachten, geblokkeerd zijn of gepauzeerd door de scheduler.
Een kernidee: wall-clock tijd van een verzoek omvat zowel on-CPU werk als off-CPU wachten.
Off-CPU tijd verbergt zich vaak achter afhankelijkheden en contentie:
Een paar signalen correleren vaak met off-CPU bottlenecks:
Deze symptomen vertellen je “we wachten,” maar niet waarop.
Off-CPU profiling schrijft tijd toe aan de reden dat je niet draaide: geblokkeerd in syscalls, wachten op locks, slapen of gedescheduled worden. Dat is krachtig voor latentiewerk omdat het vage vertragingen in actiegerichte categorieën verandert: “geblokkeerd op mutex X”, “wacht op read() van schijf” of “vast in connect() naar upstream.” Als je de wacht kunt benoemen, kun je het meten, bevestigen en verhelpen.
Prestatiewerk faalt vaak op hetzelfde moment: iemand ziet een verdacht metric, verklaart het “het probleem” en begint te tunen. Gregg’s methoden dwingen je te vertragen en te bewijzen wat het systeem beperkt voordat je iets verandert.
Een bottleneck is de resource of component die nu doorvoer beperkt of latentie gedreven heeft. Als je die verlicht, zien gebruikers verbetering.
Een hot spot is waar tijd aan besteed wordt (bijvoorbeeld een functie die vaak in een profiel voorkomt). Hot spots kunnen echte bottlenecks zijn—of gewoon druk werk dat het trage pad niet raakt.
Ruis is alles wat relevant lijkt maar dat niet is: achtergrondjobs, éénmalige pieken, sampling-artifacten, cache-effecten of “top talkers” die niet correleren met het gebruikerszichtbare probleem.
Begin met het vastleggen van een schoon voor-snapshot: het gebruikerssymptoom (latentie of foutpercentage) en de leidende kandidaat-signalen (CPU-saturatie, queue-diepte, schijf I/O, lock-contentie, enz.). Voer daarna een gecontroleerde wijziging uit die alleen je vermoede oorzaak zou moeten beïnvloeden.
Voorbeelden van causale tests:
Correlatie is een hint, geen verdict. Als “CPU stijgt wanneer latentie stijgt,” verifieer dan door CPU-beschikbaarheid te veranderen of CPU-werk te verminderen en observeer of latentie volgt.
Schrijf op: wat gemeten is, de exacte wijziging, voor/na-resultaten en de waargenomen verbetering. Dit maakt van een éénmalige winst een herbruikbaar recept voor het volgende incident—en voorkomt dat “intuïtie” later de geschiedenis herschrijft.
Prestatie-incidenten voelen urgent aan, wat precies het moment is waarop gokwerk insluipt. Een lichtgewicht, herhaalbare workflow helpt je om van “iets is traag” naar “we weten wat veranderde” te gaan zonder te veel te switchen.
Detecteer: alert op gebruikerszichtbare latentie en foutpercentages, niet alleen CPU. Laat pagen wanneer p95/p99-latentie een drempel overschrijdt voor een aanhoudend venster.
Triage: beantwoord meteen drie vragen: wat is traag, wanneer begon het en wie is getroffen? Als je de scope (service, endpoint, regio, cohort) niet kunt benoemen, ben je nog niet klaar om te optimaliseren.
Meet: verzamel bewijs dat de bottleneck versmalt. Geef de voorkeur aan tijdsgebonden captures (bijv. 60–180 seconden) zodat je “slecht” vs “goed” kunt vergelijken.
Fix: verander één ding tegelijk en meet daarna dezelfde signalen om verbetering te bevestigen en placebo uit te sluiten.
Houd een gedeeld dashboard dat iedereen tijdens incidenten gebruikt. Maak het saai en consistent:
Het doel is niet alles te grafieken; het doel is de time-to-first-fact te verkorten.
Instrumenteer de endpoints die er het meest toe doen (checkout, login, search), niet elk endpoint. Spreek voor elk af: verwachte p95, maximale foutpercentage en belangrijkste afhankelijkheid (DB, cache, derde partij).
Stem vooraf af wat er bij een volgend uitval vastgelegd moet worden:
Documenteer dit in een kort runbook (bijv. een latency-runbook), inclusief wie captures mag uitvoeren en waar artefacten worden opgeslagen.
Gregg’s methodologie draait fundamenteel om gecontroleerde verandering en snelle verificatie. Als je team diensten bouwt met Koder.ai (een chatgestuurd platform om web-, backend- en mobiele apps te genereren en itereren), sluiten twee features hier goed op aan:
Zelfs als je tijdens een incident geen nieuwe code genereert, zijn die gewoonten—kleine diffs, meetbare uitkomsten en snelle omkeerbaarheid—dezelfde gewoonten die Gregg promoot.
Het is 10:15 en je dashboard toont dat p99-latentie voor de API stijgt van ~120ms naar ~900ms tijdens piekverkeer. Het foutpercentage blijft vlak, maar klanten melden “langzame” verzoeken.
Begin service-first: Rate, Errors, Duration.
Je snijdt Duration per endpoint en ziet één route domineren in de p99: POST /checkout. Rate is 2× hoger, fouten zijn normaal, maar Duration piekt specifiek wanneer concurrency stijgt. Dat wijst op wachtrijen of contentie, niet op een volledige uitval.
Controleer vervolgens of de latentie rekenwerk is of wachten: vergelijk applicatie “handler-tijd” met totale requesttijd (of upstream vs downstream spans als je tracing hebt). Handler-tijd is laag, totale tijd is hoog—verzoeken wachten.
Maak een inventaris van waarschijnlijke bottlenecks: Utilization, Saturation, Errors voor CPU, geheugen, schijf en netwerk.
CPU-utilization is maar ~35%, maar de CPU run queue en context switches stijgen. Schijf en netwerk zien er stabiel uit. Die mismatch (lage CPU%, hoge wachttijd) is een klassiek hint: threads verbranden geen CPU—ze zijn geblokkeerd.
Je neemt een off-CPU profiel tijdens de spike en vindt veel tijd in een mutex rond een gedeelde “promotion validation” cache.
Je vervangt de globale lock door een per-key lock (of een lock-free read-path), deployt en ziet p99 terugkeren naar baseline terwijl Rate hoog blijft.
Post-incident checklist: