Memory leaks, where memory that is no longer needed is not released, can degrade the performance of Go applications over time. This guide covers common sources of memory leaks in Go applications and how to detect them using Go's profiling tools.
Go provides several built-in tools for profiling and detecting memory leaks, including pprof
, runtime/pprof
, and trace
.
pprof
is a powerful tool for profiling Go applications. It can be used to capture heap profiles and identify memory leaks.
net/http/pprof
package to enable pprof endpoints.goimport (
_ "net/http/pprof"
"net/http"
)
func main() {
// Start the HTTP server with pprof endpoints
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// Your application logic here
}
go tool pprof
to capture and analyze heap profiles.sh# Run your application
go run main.go
# In another terminal, use curl to trigger a heap profile
curl -sK -o heap.prof http://localhost:6060/debug/pprof/heap
# Use pprof to analyze the heap profile
go tool pprof heap.prof
pprof
's interactive mode to identify memory leaks.shgo tool pprof heap.prof (pprof) top (pprof) list <function_name> (pprof) web
Consider an example where a goroutine leak causes a memory leak:
gopackage main
import (
"fmt"
"time"
)
func leakyGoroutine() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for range ticker.C {
fmt.Println("Tick")
}
}
func main() {
for i := 0; i < 10; i++ {
go leakyGoroutine()
}
time.Sleep(10 * time.Second)
}
In this example, the leakyGoroutine
function starts a ticker that runs indefinitely, causing a memory leak.
To detect this leak:
net/http/pprof
and starting the HTTP server as shown earlier.curl
and pprof
.You can also use the runtime/pprof
package to programmatically create heap profiles.
goimport (
"os"
"runtime/pprof"
"log"
)
func main() {
f, err := os.Create("heap.prof")
if err != nil {
log.Fatal("could not create memory profile: ", err)
}
defer f.Close()
// Run the garbage collector to get up-to-date statistics
runtime.GC()
if err := pprof.WriteHeapProfile(f); err != nil {
log.Fatal("could not write memory profile: ", err)
}
// Your application logic here
}
go tool pprof
as shown previously to analyze the heap.prof
file.The trace
tool provides detailed execution tracing and can help identify memory leaks related to goroutines and other runtime activities.
goimport (
"os"
"runtime/trace"
"log"
)
func main() {
f, err := os.Create("trace.out")
if err != nil {
log.Fatal("could not create trace file: ", err)
}
defer f.Close()
if err := trace.Start(f); err != nil {
log.Fatal("could not start trace: ", err)
}
defer trace.Stop()
// Your application logic here
}
shgo tool trace trace.out
The trace tool provides a detailed view of the execution, including goroutine activity and memory allocations.
Detecting and fixing memory leaks in Go applications is essential for maintaining performance and stability. By using Go's built-in profiling tools such as pprof
, runtime/pprof
, and trace
, you can identify and diagnose memory leaks effectively. Regular profiling and analysis help ensure that your application remains efficient and performant.