Skip to content

Go Profiling — Performance Profiling with pprof and Trace for CPU, Memory, and Goroutines

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Go Profiling. We cover key concepts, practical examples, and best practices to help you master this topic.

Go pprof profiles CPU, memory, Goroutine, and block contention with runtime/pprof and net/http/pprof for production profiling.

What You'll Learn

  • CPU profiling
  • Memory profiling
  • HTTP pprof endpoints
  • Trace execution

Why It Matters

Profiling identifies performance bottlenecks. Docker profiles build performance. Kubernetes profiles API server latency. DodaZIP profiles compression throughput.

Real-World Use

Production performance debugging, memory leak detection, goroutine leak detection, latency optimization.

flowchart LR
    A["Profiling"] --> B["CPU Profile"]
    A --> C["Memory Profile"]
    A --> D["HTTP pprof"]
    A --> E["Trace"]
    A:::current --> B
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b

CPU Profiling

func main() {
    f, _ := os.Create("cpu.prof")
    pprof.StartCPUProfile(f)
    defer pprof.StopCPUProfile()

    // Code to profile
    expensiveOperation()
}

Memory Profiling

func main() {
    for i := 0; i < 100; i++ {
        allocateMemory()
    }

    f, _ := os.Create("mem.prof")
    pprof.WriteHeapProfile(f)
    f.Close()
}

HTTP pprof Endpoints

import _ "net/http/pprof"

func main() {
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()

    // Application code
    select {}
}

Available endpoints:

/debug/pprof/         — Overview
/debug/pprof/profile  — CPU profile (30s)
/debug/pprof/heap     — Memory profile
/debug/pprof/goroutine — Goroutine stack traces
/debug/pprof/block    — Block contention
/debug/pprof/mutex    — Mutex contention

Profiling Analysis

# CPU
go tool pprof cpu.prof
(pprof) top10
(pprof) web
(pprof) list functionName

# Interactive web UI
go tool pprof -http=:8080 cpu.prof

# From HTTP endpoint
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30

Tracing

func main() {
    f, _ := os.Create("trace.out")
    trace.Start(f)
    defer trace.Stop()

    // Code to trace
    myFunction()
}
go tool trace trace.out

Goroutine Profile

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() { defer wg.Done(); time.Sleep(time.Second) }()
    }
    wg.Wait()

    // Take goroutine profile
    pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
}

Common Mistakes

1. Profiling Without Workload

Profiling idle code gives meaningless results. Profile under realistic load.

2. Short Profiles

CPU profile default is 30 seconds. Shorter profiles may miss intermittent issues.

3. Profiling in Development Only

Production profiles reveal real bottlenecks. Use HTTP pprof in production with authentication.

4. Ignoring Goroutine Leaks

Monitor goroutine count in production. A growing count indicates leaks.

5. Not Using -http Flag

The web UI (go tool pprof -http=:8080) is more useful than CLI for exploring profiles.

Practice Questions

1. What's the difference between CPU and memory profiling? CPU profile shows where time is spent. Memory (heap) profile shows allocation hotspots.

2. How do you profile a production Go service? Import net/http/pprof, expose /debug/pprof on a separate port with authentication.

3. What does the trace tool show? Goroutine creation, GC events, network blocking, syscalls, and scheduler activity over time.

4. How do you detect a goroutine leak? Compare goroutine count over time. pprof.Lookup("goroutine").Count() shows active goroutines.

Challenge: Profile a function and identify the top 3 CPU hot spots.

Solution
# Add import _ "net/http/pprof" to your main
# Run the program
# Collect 30s CPU profile
go tool pprof http://localhost:6060/debug/pprof/profile

# In pprof shell:
top10        # Show top 10 hot spots
web          # Show flame graph
list hotFunc # Show line-by-line breakdown

FAQ

{{< faq question="What is the difference between pprof and trace?" >}} pprof shows sampling profiles (CPU, memory, goroutines). Trace shows event timeline (goroutine, GC, syscall). Use pprof for bottlenecks, trace for concurrency issues. {{< /faq >}}

{{< faq question="How do I compare two profiles?" >}} Use go tool pprof -base base.prof current.prof. Shows the difference between profiles. {{< /faq >}}

{{< faq question="Is profiling safe in production?" >}} CPU profiling adds ~5% overhead. Memory profiling is lighter. Enable pprof on an internal port behind authentication. {{< /faq >}}

{{< faq question="What is a flame graph?" >}} A visualization of stack traces. Width represents time spent. Use go tool pprof -http to view interactive flame graphs. {{< /faq >}}

{{< faq question="How do I profile a running binary?" >}} Send SIGQUIT (Ctrl+\ or kill -QUIT) to dump all goroutine stacks. Or use HTTP pprof endpoints on the running server. {{< /faq >}}

Try It Yourself

package main

import (
    "os"
    "runtime/pprof"
)

func main() {
    f, _ := os.Create("cpu.prof")
    pprof.StartCPUProfile(f)
    defer pprof.StopCPUProfile()

    sum := 0
    for i := 0; i < 1000000; i++ {
        sum += i * i
    }
    _ = sum
}

Analyze with:

go run main.go
go tool pprof cpu.prof
(pprof) top

Expected output — CPU profile showing the tight loop.

What's Next

Now that you understand profiling, explore Go modules for dependency management.

Topic Description Link
Go Modules Package management {{< ref "37-modules" >}}
Go Benchmarking Performance Testing {{< ref "35-benchmarking" >}}
Go CLI Apps Building CLI tools {{< ref "39-cli-apps" >}}

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro

Home Browse Go