We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Profiling

In the famous battle of Helm's Deep, Aragorn and Théoden were atop the walls, monitoring as the battle unfolded. When an alert came that the outer wall was weakening, they went down into the culvert to see the situation up close and personal. In an application, this sort of situation calls for the mighty power of profiling!

Profiling is the practice of taking measurements of your running program to learn where it's spending the most CPU cycles, memory, context switches, or other interesting characteristics.

Types of Profiling

Just as we have metrics for a variety of different aspects of our application, we also have different types of profiling – and sometimes they clearly overlap with our metrics.

  • CPU utilization – Can tell you how much execution time is spent in specific parts of your program.
  • Memory (Heap) utilization – Will tell you which parts of your program use the most memory.
  • Thread (or in our case, goroutine) usage – Can help identify logic bugs or resource leaks related to concurrency.
  • Blocking calls – Reveals which parts of code spend time waiting for something to happen.
  • Execution Tracing – Useful when you need a detailed timeline of events for a particular code execution flow.

Profiling Tools

If you've ever done front-end development, you're likely familiar with the Dev Tools of your favorite browser. Go gives us some of the same capabilities, but with a different interface. The two main profiling tools that come with Go are:

  • runtime/pprof – Go's built-in profiling system for profiling a running Go application.
  • testing benchmarks – Custom-built Benchmarking functions, controlled by Go's test suite tools.

Profile-Driven Development

Profiling is best used when facing a specific problem. I'd recommend against running the profiler to poke around for optimization opportunities in random places – a clear example of premature optimization. Instead, wait until you're asking these sorts of questions:

  • Why is a certain operation taking so long?
  • Why is the program crashing due to Out-of-Memory errors?
  • Why are certain tasks just getting stuck?

These are great times to pull out Profile-Driven Development!

Profile-Guided Optimization

One small exception to the rule of premature optimization with profilers is PGO, or Profile-Guided Optimization.

PGO is a compiler optimization technique that feeds information (a profile) from representative runs of the application back into the compiler for the next build of the application, which uses that information to make more informed optimization decisions.

It's beyond the scope of this course, but good to know about in case you want to explore later.