# Go Profiling en Benchmarking in 2026: pprof, trace en Sollicitatievragen > Uitgebreide gids voor Go profiling met pprof, execution tracing en benchmark profiling. Bevat praktische sollicitatievragen over Go performance optimalisatie. - Published: 2026-09-19 - Updated: 2026-09-19 - Author: Anthony Fillion-Maillet - Tags: go, profiling, benchmarking, performance, pprof, sollicitatie - Reading time: 12 min --- Go profiling met pprof en het `runtime/trace` pakket transformeert giswerk naar data. Performance vragen komen voor in de meeste Go sollicitatiegesprekken, en kandidaten die een flame graph kunnen lezen of uitleggen wanneer `-inuse_space` versus `-allocs` gebruikt moet worden, onderscheiden zich duidelijk. De tooling wordt meegeleverd met de standaard library, vereist geen externe dependencies en integreert direct met benchmarks. > **Profieltypen om te Kennen** > > Go 1.24+ biedt zeven ingebouwde profielen: CPU, heap, allocs, goroutine, threadcreate, block en mutex. Go 1.26 voegde een experimenteel goroutine leak profiel toe dat onbereikbare geblokkeerde goroutines detecteert. ## CPU Profiling met pprof: Het Startpunt CPU profiling bemonstert de call stack op regelmatige intervallen (standaard 100 Hz) en registreert welke functies processortijd verbruiken. Het `runtime/pprof` pakket regelt de low-level verzameling, terwijl `go tool pprof` de resultaten analyseert. Een 30-seconden profiel vangt 3000 samples, voldoende voor statistische significantie in de meeste applicaties. Een standalone programma schakelt profiling in door `pprof.StartCPUProfile` aan te roepen bij het opstarten. Het profiel schrijft naar een bestand dat `go tool pprof` later leest: ```go // main.go package main import ( "flag" "log" "os" "runtime/pprof" ) var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") func main() { flag.Parse() if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { log.Fatal(err) } defer f.Close() pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } // Application logic here } ``` Voor HTTP servers volstaat het importeren van `net/http/pprof` als side effect. Het pakket registreert automatisch handlers op `/debug/pprof/`. Geen verdere codewijzigingen zijn nodig: ```go // server.go package main import ( "net/http" _ "net/http/pprof" // Registers /debug/pprof/* handlers ) func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } ``` Haal een 30-seconden CPU profiel op van een draaiende server met `go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30`. De tool downloadt het profiel en opent een interactieve shell. De `seconds` parameter bepaalt de verzamelduur. ## Profielen Analyseren: top, list en Flame Graphs De pprof shell biedt commando's om bottlenecks te identificeren. `top` toont de functies die de meeste CPU tijd verbruiken, gesorteerd op flat time. Het `list` commando toont broncode met timing annotaties per regel, en lokaliseert exact de regels die de uitvoering domineren. ```bash # Terminal session with go tool pprof $ go tool pprof cpu.prof (pprof) top 10 Showing nodes accounting for 4.2s, 85% of 4.9s total flat flat% sum% cum cum% 1.8s 36.73% 36.73% 1.8s 36.73% runtime.memmove 0.9s 18.37% 55.10% 0.9s 18.37% encoding/json.(*decodeState).scanWhile 0.5s 10.20% 65.30% 2.3s 46.94% main.processRecords ... (pprof) list processRecords Total: 4.9s 0.5s 2.3s (flat, cum) 46.94% of Total 20: for _, r := range records { 21: 0.3s 0.3s data := json.Marshal(r) 22: 0.2s 2.0s result := transform(data) ... ``` De web interface voegt visuele analyse toe. Draai `go tool pprof -http=:6060 cpu.prof` om een browser te openen met flame graphs, directed graphs en source views. Sinds Go 1.26 verschijnen flame graphs als standaardweergave in de web UI. Flame graphs tonen de call hierarchy horizontaal, waarbij bredere balken meer tijd in die functie en de aangeroepen functies aangeven. > **Flame Graphs Lezen** > > In een flame graph representeert de x-as de populatie van samples, niet de tijd. Elke box is een functie, en de breedte toont hoe vaak die functie in samples voorkwam. Parent functies bevinden zich onder hun children. Zoek naar brede plateaus bovenaan: die functies doen het daadwerkelijke werk. ## Memory Profiling: Heap vs Allocs Memory profiling beantwoordt twee verschillende vragen. Het **heap** profiel (`-inuse_space`) toont wat geheugen vasthoudt op het moment van capture. Het **allocs** profiel toont waar allocaties plaatsvonden over tijd, zelfs als dat geheugen inmiddels is vrijgegeven. Om het huidige geheugengebruik te reduceren wordt het heap profiel onderzocht. Om de allocatiesnelheid en GC druk te verminderen wordt het allocs profiel geanalyseerd. Hoge allocatiesnelheden triggeren frequente garbage collection, wat goroutines pauzeert en CPU gebruik verhoogt. ```bash # Capture heap profile from running server $ curl -o heap.prof http://localhost:8080/debug/pprof/heap $ go tool pprof -inuse_space heap.prof # Capture allocs profile (allocation count over 30s) $ curl -o allocs.prof "http://localhost:8080/debug/pprof/allocs?seconds=30" $ go tool pprof -alloc_objects allocs.prof ``` De `-inuse_objects` flag telt levende objecten in plaats van bytes, nuttig voor het identificeren van geheugenfragmentatie. De `-alloc_space` flag toont het totaal aantal gealloceerde bytes over de profielperiode, en onthult functies die snel door geheugen gaan ook al geven ze het snel vrij. Veelvoorkomende allocatie hotspots omvatten string concatenatie in loops (gebruik `strings.Builder`), interface conversies die naar de heap escapen, en slice groei zonder preallocatie. De [Go compiler documentatie](https://go.dev/doc/diagnostics#profiling) legt escape analysis in detail uit. ## Benchmark Profiling met testing.B Het `testing` pakket integreert profiling direct in benchmarks. Deze combinatie isoleert specifieke code paths zonder de ruis van een volledige applicatie. Benchmark profiling beantwoordt de vraag: "Hoe presteert deze functie in isolatie?" ```go // parser_test.go package parser import "testing" func BenchmarkParseJSON(b *testing.B) { data := []byte(`{"id":1,"name":"test","values":[1,2,3]}`) b.ReportAllocs() // Include allocation stats b.ResetTimer() // Exclude setup from timing for i := 0; i < b.N; i++ { _, _ = Parse(data) } } ``` Genereer profielen tijdens benchmark uitvoering met flags. De `-cpuprofile` en `-memprofile` flags schrijven profielen naar bestanden voor latere analyse: ```bash # CPU profile during benchmark $ go test -bench=BenchmarkParseJSON -cpuprofile=cpu.prof -benchtime=5s # Memory profile during benchmark $ go test -bench=BenchmarkParseJSON -memprofile=mem.prof -benchtime=5s # Analyze the result $ go tool pprof -http=:6060 cpu.prof ``` De `-benchtime` flag bepaalt hoe lang de benchmark draait. Langere runs produceren accuratere profielen maar kosten meer tijd. Een 5-seconden run levert doorgaans stabiele resultaten. Voor micro-benchmarks, gebruik `-count=10` om meerdere iteraties te draaien en op variantie te controleren. ## Execution Tracing met runtime/trace Terwijl pprof toont waar tijd wordt besteed, toont `runtime/trace` wanneer events plaatsvinden. De trace vangt goroutine scheduling, system calls, GC events en netwerkactiviteit op een tijdlijn. Deze zichtbaarheid in concurrency gedrag complementeert statistisch profilen. ```go // trace_example.go package main import ( "os" "runtime/trace" ) func main() { f, _ := os.Create("trace.out") defer f.Close() trace.Start(f) defer trace.Stop() // Application logic runConcurrentTasks() } ``` De trace viewer toont goroutine levensduren, blocking events en processor gebruik. Elke goroutine verschijnt als een horizontale balk, met kleuren die aangeven of deze draaide, geblokkeerd was of wachtte op scheduling: ```bash $ go tool trace trace.out # Opens browser at http://127.0.0.1:port ``` Voor HTTP servers, haal een trace op van `/debug/pprof/trace?seconds=5`. De trace viewer toont welke goroutines waarop blokkeerden, en onthult contention patronen die CPU profielen missen. De "Goroutine analysis" view groepeert goroutines per creatiepunt, wat helpt bij het identificeren van leaks of onverwachte fan-out. Traces zijn zwaarder dan profielen. Een 5-seconden trace van een drukke server kan honderden megabytes aan data produceren. Gebruik korte duren en gerichte verzameling. De [Go blog over execution tracing](https://go.dev/blog/execution-traces-2024) behandelt geavanceerde analysetechnieken. ## Block en Mutex Profiling voor Contention Block profiling registreert goroutines die wachten op synchronisatie primitieven: channels, mutexes en condition variables. Mutex profiling focust specifiek op mutex contention. Deze profielen onthullen concurrency bottlenecks die onzichtbaar zijn voor CPU profiling. Schakel deze profielen in door runtime parameters te zetten voordat de contention optreedt: ```go // Enable block profiling (1 = sample all blocking events) runtime.SetBlockProfileRate(1) // Enable mutex profiling (1 = sample all mutex contention) runtime.SetMutexProfileFraction(1) ``` Voor productie, stel hogere waarden in om overhead te verminderen. Een block profile rate van 1000000 (een microseconde) of mutex fraction van 100 levert nuttige data met minimale impact. Te lage waarden vangen elk event en kunnen de applicatie vertragen. Haal deze profielen op van de standaard endpoints: ```bash $ curl -o block.prof http://localhost:8080/debug/pprof/block $ curl -o mutex.prof http://localhost:8080/debug/pprof/mutex $ go tool pprof block.prof ``` Block profielen tonen totale wachttijd, niet het aantal blocking events. Een functie die eenmaal 1 seconde blokkeert ziet er identiek uit als een die 1000 keer voor 1 milliseconde blokkeert. Execution tracing onderscheidt deze gevallen. ## Veelvoorkomende Profiling Valkuilen Profiling introduceert overhead die resultaten kan scheeftrekken. CPU profiling voegt ongeveer 5% overhead toe. Memory profiling bemonstert allocaties (1 per 512KB standaard), dus kleine allocaties verschijnen mogelijk niet. Tracing vangt elk event en kan 10-30% overhead toevoegen. Meerdere fouten leiden tot misleidende profielen: **Geoptimaliseerde builds anders profileren.** Altijd profileren met dezelfde build flags als in productie. Debug builds schakelen inlining en optimalisaties uit, waardoor hot spots op andere plaatsen verschijnen. **Profileren onder kunstmatige load.** Een profiel van een inactieve server toont de idle loop, niet echte bottlenecks. Profileer onder realistische traffic patronen. **GC overhead negeren.** CPU profielen bevatten tijd besteed aan garbage collection. Een hoge `runtime.gc*` aanwezigheid duidt op geheugenallocatie problemen, niet CPU problemen. Adresseer die met memory profiling. **Korte profiling duren.** Een 1-seconden profiel vangt slechts 100 samples. Statistische ruis domineert. Profileer minstens 30 seconden onder stabiele load. ## Go Sollicitatievragen over Profiling Performance vragen testen of een kandidaat echte problemen kan diagnosticeren. Interviewers zoeken naar vertrouwdheid met de tooling en begrip van wat elk profiel onthult. **V: Wanneer toont heap profiling andere resultaten dan allocs profiling?** Heap toont geheugen dat vastgehouden wordt op capture moment. Allocs toont alle allocaties, inclusief vrijgegeven geheugen. Een functie die tijdelijke buffers alloceert in een loop verschijnt in allocs maar niet in heap als de buffers verzameld zijn voor de snapshot. Gebruik allocs om GC druk te verminderen, heap om leaks te vinden. **V: Een goroutine lijkt vast te zitten. Welk profiel helpt?** Het goroutine profiel toont stack traces van alle goroutines. Het block profiel toont waar goroutines wachten. Voor Go 1.26+ detecteert het experimentele goroutine leak profiel onbereikbare goroutines geblokkeerd op channels of mutexes. Execution tracing toont de tijdlijn van blocking events. **V: Wat betekent flat percentage versus cumulatief percentage in pprof?** Flat meet tijd in de functie zelf. Cumulatief bevat tijd in aangeroepen functies. Een functie met hoog cumulatief maar laag flat is een coordinator die werk delegeert. Een functie met hoog flat doet de daadwerkelijke berekening. Optimaliseer eerst functies met hoog flat. **V: Hoe profileer je een benchmark zonder de test setup te profileren?** Roep `b.ResetTimer()` aan na het afronden van de setup. Voor benchmarks met per-iteratie setup, gebruik `b.StopTimer()` en `b.StartTimer()` rond de setup code. De timer calls hebben nanoseconde overhead, dus vermijd ze in tight loops. **V: Waarom zou een functie niet in een CPU profiel verschijnen ondanks traag zijn?** CPU profiling vangt alleen functies die actief CPU gebruiken. I/O-gebonden functies (wachtend op netwerk, disk of channels) verschijnen in block profielen of traces, niet in CPU profielen. Sampling kan ook functies missen die in totaal minder dan 10ms draaien. **V: Hoe beinvloedt de Go 1.24 Swiss Tables map implementatie profiling?** Go 1.24 verving de bucket-gebaseerde map met Swiss Tables, wat CPU overhead met 2-3% verminderde voor map-intensieve workloads. Profielen genomen voor en na de upgrade tonen verschillende map-gerelateerde call stacks. De `GOEXPERIMENT=noswissmap` flag keert terug naar de oude implementatie voor vergelijking. ## Continuous Profiling in Productie Momentopname profielen missen voorbijgaande problemen. Continuous profiling tools zoals [Pyroscope](https://pyroscope.io/) of [Parca](https://www.parca.dev/) verzamelen continue low-overhead samples, waarmee vergelijkingen over deployments mogelijk zijn. Deze tools correleren profielen met metrics en traces. Go's ingebouwde profielen werken met deze tools via het pprof formaat. De [pprof.me](https://pprof.me/) service voegde vergelijkingsfuncties toe in 2026, waarmee upload en diff van profielen mogelijk is om optimalisatie-impact te kwantificeren voor en na codewijzigingen. Voor [Go sollicitatievoorbereiding](/technologies/go/interview-questions/testing) is begrip van zowel de tooling als de onderliggende concepten belangrijk. Het [context pakket](/technologies/go/interview-questions/context-package) en [concurrency patterns](/technologies/go/interview-questions/concurrency-patterns) komen vaak samen met profiling vragen voor. Performance optimalisatie vereist vaak het combineren van profiling data met kennis van Go's runtime gedrag. ## Wat Go Profiling Onthult over Applicatiegedrag - CPU profielen identificeren hot functions maar missen I/O-gebonden werk. Combineer met trace voor het volledige beeld. - Memory profielen onderscheiden retentie problemen (heap) van allocatie churn (allocs). Gebruik `-inuse_space` voor leaks, `-alloc_space` voor GC druk. - Block en mutex profielen onthullen contention die CPU profielen niet kunnen zien. Schakel ze in wanneer latency piekt onder load. - Benchmark profiling isoleert specifieke code paths. Roep altijd `b.ReportAllocs()` en `b.ResetTimer()` aan voor accurate metingen. - De trace viewer toont goroutine scheduling en blocking events op een tijdlijn, essentieel voor het diagnosticeren van concurrency bugs. - Go 1.24 runtime verbeteringen reduceerden CPU overhead met 2-3% door Swiss Tables maps en een nieuwe mutex implementatie. - Productie profiling met de `/debug/pprof/` endpoints vereist authenticatie. Stel deze endpoints nooit publiek bloot: ze lekken interne applicatiestatus en kunnen denial-of-service mogelijk maken door dure profielverzameling. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/nl/blog/go/go-profiling-benchmarking-pprof-trace-interview