I'm using Go's pprof tool to investigate my service's memory usage. Almost all of the memory usage comes from a single function that sets up multiple bounded-queue channels. I'm somewhat confused by what pprof is telling me here:
$ go tool pprof ~/pprof/pprof.server.alloc_objects.alloc_space.inuse_objects.inuse_space.007.pb.gz
File: server
Type: inuse_space
Time: Dec 21, 2020 at 10:46am (PST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) list foo
Total: 102.73MB
ROUTINE ======================== github.com/******/foo in ***.go
79.10MB 79.10MB (flat, cum) 77.00% of Total
. . 135:
. . 136:func foo() {
. . 137:
14.04MB 14.04MB 138: chanA := make(chan chanAEntry, bufferSize)
. . 139: defer close(chanA)
. . 140:
. . 141:
19.50MB 19.50MB 142: chanB := make(chan chanBCEntry, bufferSize)
. . 143: defer close(chanB)
. . 144:
. . 145:
27.53MB 27.53MB 146: chanC := make(chan chanBCEntry, bufferSize)
. . 147: defer close(chanC)
. . 148:
. . 149:
7.92MB 7.92MB 150: chanD := make(chan chanDEntry, bufferSize)
. . 151: defer close(chanD)
. . 152:
It looks like line 142 is responsible for 19.50MB of allocations and line 146 is responsible for 27.53MB, but those lines are doing the same thing - they create buffered channels with the same input type and the same capacity.
- Is this an artifact of the fact that pprof does random sampling?
- Does Go allocate channels lazily (fwiw, after letting the service run for a few days these values eventually equalize)?
- Is pprof reporting the memory required by the objects sent along the channel as well as the memory required by the channel itself?