Sobes.tech
Middle

How can you measure memory usage in Go and what is pprof?

sobes.tech AI

Answer from AI

Memory usage in Go can be measured in several ways:

  • runtime.MemStats: Provides a snapshot of memory statistics, including heap size, number of objects, garbage collection, etc. Useful for getting an overall view of memory distribution.

  • Profiler pprof: A powerful tool for performance and resource usage analysis, including memory. Allows collecting heap profiles at different times and analyzing them to identify bottlenecks and memory leaks.

  • debug.FreeOSMemory(): Forces the release of memory back to the operating system. Can indirectly help understand how much memory the Go runtime is holding.

pprof (net/http/pprof) — is a package in the Go standard library that integrates with the pprof profiler from the runtime/pprof package. It provides HTTP interfaces for collecting profiles of various resources, including CPU, heap (memory), blocking, goroutine, and mutex.

To use it:

  1. Import net/http/pprof.
  2. Start an HTTP server.
  3. Access the profiles via the appropriate URLs (/debug/pprof/).
  4. Use the go tool pprof utility to analyze the collected data.

Example of using runtime.MemStats:

import (
	"fmt"
	"runtime"
	"time"
)

func main() {
	var m runtime.MemStats
	runtime.ReadMemStats(&m) // Read memory statistics
	fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
	fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
	fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
	fmt.Printf("\tNumGC = %v\n", m.NumGC)

	// Example of working with memory
	_ = make([]byte, 1024*1024*10) // Allocate 10MB

	time.Sleep(100 * time.Millisecond) // Wait for GC to run

	runtime.ReadMemStats(&m)
	fmt.Printf("After allocation: Alloc = %v MiB", bToMb(m.Alloc))
	fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
	fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
	fmt.Printf("\tNumGC = %v\n", m.NumGC)
}

func bToMb(b uint64) uint64 {
	return b / 1024 / 1024
}

Example of using pprof in an HTTP server:

import (
	_ "net/http/pprof" // Import for registering pprof handlers
	"net/http"
	"log"
)

func main() {
	log.Println(http.ListenAndServe(":6060", nil)) // Listen on port 6060
}

After running this code, you can visit http://localhost:6060/debug/pprof/ to access various profiles. To analyze the heap, you can use go tool pprof http://localhost:6060/debug/pprof/heap.