Skip to main content

Posts

Showing posts with the label Concurrency

Debugging Go Memory Leaks: Detecting Orphaned Goroutines with pprof

  The most insidious memory leaks in Go services rarely stem from large, cached structs or uncleared maps. Instead, they manifest as a slow, inexorable rise in resident set size (RSS) that persists despite aggressive garbage collection cycles. In my experience, 80% of these cases are not "memory" leaks in the traditional sense. They are  goroutine leaks . When a goroutine blocks indefinitely, it never terminates. Because the Go runtime considers every active goroutine a root for garbage collection, the goroutine’s stack and every variable reachable from that stack cannot be freed. A 2KB stack can easily hold references to 20MB of heap data. If your service spawns 100 leaky goroutines per minute, you will OOM. The Root Cause: Orphaned Concurrency Under the hood, a goroutine is simply a managed thread of execution. When a goroutine enters a blocked state (e.g., waiting on a channel send/receive, acquiring a mutex, or waiting on network I/O), the Go scheduler parks it ( runtime....