Profiling Go Code: Finding Bottlenecks with pprof and trace

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Profiling Go Code: Finding Bottlenecks



Performance optimization is one of the key tasks for a developer, especially when dealing with high-load systems in Go. However, before optimizing anything, you need to know exactly which code sections are bottlenecks. This is where profiling comes in — collecting and analyzing program execution metrics.



In this article, we will cover how to profile Go applications using built-in tools: pprof and trace. You will learn how to find problem areas related to CPU, memory, blocking, and goroutines, as well as how to interpret the obtained data.



What is profiling and why is it needed?



Profiling is the process of collecting data about a program's operation during its execution. This data helps answer questions:



  • Which functions consume the most CPU time?
  • Where does a large amount of memory allocation occur?
  • Which goroutines are blocked and on what?
  • How long does a system call or I/O operation take?


Go provides powerful profiling tools right out of the box. The main ones are net/http/pprof for web applications and runtime/pprof for CLI utilities.



The pprof tool: CPU and Memory profiles



pprof is the main tool for profiling Go. It can collect CPU, memory, blocking, goroutine, and mutex contention profiles.



Adding pprof to a web application



The easiest way to enable profiling is to import the net/http/pprof package:



package main

import ( "net/http" _ "net/http/pprof" // registers pprof handlers)

func main() { // Your application http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)}


After this, various profiles will be available at /debug/pprof/. For example:



  • /debug/pprof/profile — CPU profile (default 30 seconds)
  • /debug/pprof/heap — memory profile (heap)
  • /debug/pprof/goroutine — dump of all goroutines
  • /debug/pprof/block — blocking profile


Collecting a CPU profile



To collect a CPU profile, use the command:



go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30


After collection completes, the interactive pprof console will open. The most useful commands:



  • top — show functions consuming the most CPU
  • list <function> — show line-by-line time breakdown
  • web — open call graph in browser (requires Graphviz)
  • peek <function> — show callers and callees


Example top output:



Showing nodes accounting for 3.50s, 70% of 5.00s total      flat  flat%   sum%        cum   cum%     1.20s 24.00% 24.00%      1.20s 24.00%  encoding/json.(*Decoder).Decode     0.80s 16.00% 40.00%      0.80s 16.00%  runtime.mallocgc     0.60s 12.00% 52.00%      1.80s 36.00%  main.processData     0.50s 10.00% 62.00%      0.50s 10.00%  runtime.memmove     0.40s  8.00% 70.00%      0.40s  8.00%  strings.ToLower


Collecting a memory profile



To analyze memory usage:



go tool pprof http://localhost:8080/debug/pprof/heap


Important commands in pprof for memory:



  • top — functions allocating the most memory
  • sample_index=alloc_space — switch to total allocated memory
  • sample_index=inuse_space — switch to currently used memory
  • tr

Blogs

Book Recommendations