Go tracking and troubleshooting¶
To investigate the Go portion of the process memory, you can use the usual and expected tooling available to any Go binary. If you encounter a leak in the Agent process as seen in the process RSS, review the Go memory profile. If everything is okay, the leak may be elsewhere.
The usual way to profile go binary memory usage is via the pprof
facilities:
- Run
go tool pprof http://localhost:5000/debug/pprof/heap
to jump into thepprof
interpreter and load the heap profile. - Run
curl localhost:5000/debug/pprof/heap > myheap.profile
to save a heap profile to disk. Note: You may have to do this on a box without theGo
toolchain. - Use
go tool pprof
to analyze the profile.
Note: You have multiple other profiles on other parts of the Go runtime you can dump: goroutine
, heap
, threadcreate
, block
, mutex
, profile
and trace
. This doc only covers heap
profiling.
You can normally jump into pprof
in interactive mode easily and load the profile:
There are several tools available to explore the heap profile, most notably the top
tool. Use the top
tool to list the top memory hungry elements, including cumulative and sum statistics to produce an input similar to below:
(pprof) top
Showing nodes accounting for 4848.62kB, 100% of 4848.62kB total
Showing top 10 nodes out of 31
flat flat% sum% cum cum%
1805.17kB 37.23% 37.23% 1805.17kB 37.23% compress/flate.NewWriter
858.34kB 17.70% 54.93% 858.34kB 17.70% github.com/DataDog/datadog-agent/vendor/github.com/modern-go/reflect2.loadGo17Types
583.01kB 12.02% 66.96% 2388.18kB 49.25% github.com/DataDog/datadog-agent/pkg/serializer/jsonstream.(*PayloadBuilder).Build
553.04kB 11.41% 78.36% 553.04kB 11.41% github.com/DataDog/datadog-agent/vendor/github.com/gogo/protobuf/proto.RegisterType
536.37kB 11.06% 89.43% 536.37kB 11.06% github.com/DataDog/datadog-agent/vendor/k8s.io/apimachinery/pkg/api/meta.init.ializers
512.69kB 10.57% 100% 512.69kB 10.57% crypto/x509.parseCertificate
0 0% 100% 1805.17kB 37.23% compress/flate.NewWriterDict
0 0% 100% 1805.17kB 37.23% compress/zlib.(*Writer).Write
0 0% 100% 1805.17kB 37.23% compress/zlib.(*Writer).writeHeader
0 0% 100% 512.69kB 10.57% crypto/tls.(*Conn).Handshake
or tree
:
(pprof) tree
Showing nodes accounting for 4848.62kB, 100% of 4848.62kB total
----------------------------------------------------------+-------------
flat flat% sum% cum cum% calls calls% + context
----------------------------------------------------------+-------------
1805.17kB 100% | compress/flate.NewWriterDict
1805.17kB 37.23% 37.23% 1805.17kB 37.23% | compress/flate.NewWriter
----------------------------------------------------------+-------------
858.34kB 100% | github.com/DataDog/datadog-agent/vendor/github.com/modern-go/reflect2.init.0
858.34kB 17.70% 54.93% 858.34kB 17.70% | github.com/DataDog/datadog-agent/vendor/github.com/modern-go/reflect2.loadGo17Types
----------------------------------------------------------+-------------
2388.18kB 100% | github.com/DataDog/datadog-agent/pkg/serializer.Serializer.serializeStreamablePayload
583.01kB 12.02% 66.96% 2388.18kB 49.25% | github.com/DataDog/datadog-agent/pkg/serializer/jsonstream.(*PayloadBuilder).Build
1805.17kB 75.59% | github.com/DataDog/datadog-agent/pkg/serializer/jsonstream.newCompressor
----------------------------------------------------------+-------------
553.04kB 100% | github.com/DataDog/datadog-agent/vendor/github.com/gogo/googleapis/google/rpc.init.2
553.04kB 11.41% 78.36% 553.04kB 11.41% | github.com/DataDog/datadog-agent/vendor/github.com/gogo/protobuf/proto.RegisterType
----------------------------------------------------------+-------------
536.37kB 100% | runtime.main
536.37kB 11.06% 89.43% 536.37kB 11.06% | github.com/DataDog/datadog-agent/vendor/k8s.io/apimachinery/pkg/api/meta.init.ializers
----------------------------------------------------------+-------------
512.69kB 100% | crypto/x509.ParseCertificate
512.69kB 10.57% 100% 512.69kB 10.57% | crypto/x509.parseCertificate
----------------------------------------------------------+-------------
...
There are several facets to inspect your profiles: - inuse_space
: Display in-use memory size - inuse_objects
: Display in-use object counts - alloc_space
: Display allocated memory size - alloc_objects
: Display allocated object counts
In interactive mode, select and change modes by entering the moce and hitting enter
.
Another useful feature is the allocation graph, or what the top
and tree
commands show in text mode graphically. Open the graph directly in your browser using the web
command, or if you'd like to export it to a file, use the svg
command or another graph exporting commands.
Another useful profile you can use if RSS is growing and you cannot resolve the issue is the goroutines
profile. It is useful for identifying Go routine leaks, which is another common issue in Go development:
Load into pprof
and explore in the same way as noted above.
This section will help you get started, but there is more information available in the links below.