Understanding the Go Runtime: Profiling
6 days ago
- #Performance Analysis
- #Runtime Internals
- #Go Profiling
- The reflect package uses type descriptors compiled at build time, while profiling captures runtime data through call stacks.
- Go provides five profiles (CPU, heap, block, mutex, goroutine) with a shared pprof format based on a simple protocol buffer structure.
- Profiles share a common skeleton with indirection: samples reference locations, which reference functions, which reference strings in a shared table for efficiency.
- CPU profiling uses asynchronous signal-driven collection with a ring buffer to avoid allocation and locking in handlers.
- Heap, block, and mutex profiles use in-place aggregation into hash tables (buckets) keyed by call stacks, triggered by specific runtime events.
- Heap profiling samples allocations based on a randomized rate, scaling counts to estimate totals, and tracks live vs. allocated objects.
- Block and mutex profiles record contention events, with selective sampling by duration or random fraction, and scale values to estimate true totals.
- Goroutine profiling takes an on-demand snapshot of all live goroutines, using a cooperative approach to avoid long stop-the-world pauses.
- All profiles ultimately produce the same pprof file format, with differences in how and when stacks are captured and aggregated.