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

Memory Profiling

CPU and memory profiling are the two types you're most likely to use. Let's look at memory profiling now.

The mechanics of gathering the profile are essentially the same. We just use the /heap endpoint in place of /profile:

curl http://localhost:XXXX/debug/pprof/heap?seconds=30 --output memory.prof

Once you've gathered your profile, you can examine it using the same CLI tool:

go tool pprof /path/to/linko memory.prof

As with the CPU profile, you can use the top command to see which functions account for the most memory in the captured profile.

(pprof) top
Showing nodes accounting for 8.19MB, 100% of 8.19MB total
      flat  flat%   sum%        cum   cum%
    4.00MB 48.85% 48.85%     4.00MB 48.85%  linko/internal/foo.buildResponse
    2.19MB 26.75% 75.60%     2.19MB 26.75%  encoding/json.(*Encoder).Encode
    2.00MB 24.40%   100%     2.00MB 24.40%  bytes.makeSlice
  • flat refers to memory attributed directly to the named function
  • cum refers to cumulative memory attributed to that function and all its callees.

GraphViz

For memory profiling, there's an even better way to visualize the profile: as a graph.

go tool pprof can emit Graphviz DOT output, which can then be converted into an image for visualization. Here's how:

go tool pprof -dot /path/to/linko memory.prof | dot -Tsvg -o memory.svg

This creates a memory.svg file that you can open in an image viewer or web browser. You should see a directed graph of nodes, where each node represents a function, and arrows indicate the function-call flow.

The graph shows functions that cumulatively consumed more memory as larger nodes. This makes it easy to see very quickly which functions are likely to warrant the most attention. Look especially for large nodes with smaller nodes directly downstream. Since the node size represents cumulative memory allocation, it's those big-to-small jumps that most likely indicate that the upstream function is consuming a lot of memory itself.

Of course, not all functions are called from the same place every time. And you may even have recursive functions. In some cases, this can make interpreting the graph a bit more challenging, but the visual representation should make it more or less clear what's happening.

Assignment

Linko has a memory leak!

  1. go build -o linko . && ./linko
    
  2. curl -u frodo:ofTheNineFingers "http://localhost:8899/debug/pprof/heap?seconds=30" --output memory.prof
    
  3. ./spamredirect.sh 200
    
  4. go tool pprof -dot linko memory.prof | dot -Tsvg -o memory.svg
    
    Did you figure it out? I'll ask you about it in the next lesson.
  5. go tool pprof -top -inuse_space "http://frodo:ofTheNineFingers@localhost:8899/debug/pprof/heap?seconds=30" > memory.pprof.txt
    
  6. ./spamredirect.sh 200
    

When the profiler is done, run and submit the CLI tests from the root of the Linko repo.