Go version
go version go1.25.0 darwin/arm64
Output of go env
in your module/workspace:
AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN='/Users/glen/.local/share/mise/installs/go/1.25.0/bin'
GOCACHE='/Users/glen/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/glen/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/0y/vtlpbcf55j1_jvbs92x2fsrh0000gn/T/go-build849456377=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/glen/Development/Geckoboard/turnstile/go.mod'
GOMODCACHE='/Users/glen/go/pkg/mod'
GONOPROXY='github.com/geckoboard'
GONOSUMDB='github.com/geckoboard'
GOOS='darwin'
GOPATH='/Users/glen/go'
GOPRIVATE='github.com/geckoboard'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/glen/.local/share/mise/installs/go/1.25.0'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/glen/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/Users/glen/.local/share/mise/installs/go/1.25.0/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.25.0'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
I am attempting to get a trace of allocations being performed on a small amount of code for optimization purposes
As documented here: https://go.dev/wiki/Performance#memory-allocator-trace
So I ran
GODEBUG=traceallocfree=1 go test .
What did you see happen?
Just the output of my tests running
What did you expect to see?
When running under Go 1.19 the flag produces large amounts of allocation trace information
I was able to find https://github.com/golang/go/issues/68885, which has been closed and locked, and links to https://go-review.googlesource.com/c/go/+/583376 - however that CL does not reference any related Go issue or explanation.
I can see a related CL https://go-review.googlesource.com/c/go/+/583377/4 that refers to a GODEBUG of traceallocfree
, but I can find no further reference to this anywhere else, and enabling it when executing a binary does not appear to do anything
What is the current state of allocation tracing?
Comment From: gabyhelp
Related Issues
- runtime: GODEBUG=allocfreetrace=1 not working as go1.19.2 in go1.23.0 #68885 (closed)
- Args in empty no-op functions cause allocations #30953 (closed)
- GODEBUG=gctrace=1 ./myapp, the output heap goal incorrect? #68643 (closed)
- proposal: runtime: provide access to info about recent GC cycles #28623
Related Code Changes
Related Documentation
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: ianlancetaylor
allocfreetrace
was removed in https://go.dev/cl/583376. This should have been documented in the Go 1.23 release notes. It should be removed from the wiki page. Thanks for reporting this. CC @mknyszek
Comment From: glenjamin
allocfreetrace
was removed in go.dev/cl/583376. This should have been documented in the Go 1.23 release notes. It should be removed from the wiki page. Thanks for reporting this. CC @mknyszek
To be clear, as well as the removal I was hoping to see what the recommended replacement for this was and how to use it
Comment From: cherrymui
cc @golang/runtime
Comment From: mknyszek
Apologies -- this feature was so under-used that I didn't realize there even was documentation for it outside of the runtime package. It's extremely slow and produces a lot of data, and a lot of it is irrelevant because the runtime itself allocates memory on startup. My understanding at the time was that it was solely used by the Go team for debugging.
We can add it back for the purposes of getting a trace of allocations in very short code paths.
Unfortunately allocfreetrace
doesn't yet have the necessary tooling to make it easy to use out of the box. allocfreetrace
has almost everything you would want (I guess except a stack trace at each allocation...), but it is much more annoying to use today. You need to (1) collect an execution trace with the GODEBUG
set, (2) use the golang.org/x/exp/trace package to parse it, (3) observe and interpret EventExperimental
events which give raw access to the data, but the decoding isn't straightforward because we play a lot of tricks to pack the necessary information.
This convoluted process is okay for someone debugging the runtime, but it is clearly not in a state to be used by regular Go developers.
Comment From: glenjamin
We can add it back for the purposes of getting a trace of allocations in very short code paths.
This was my core use-case, I had a small bit of code I was trying to optimize, a bench test can tell me the number of allocations per operation, but I was trying to find the "correct" way to get a list of those allocations.
Some searching around for advice on this pointed me towards allocfreetrace
as one way to do this, but I'm not especially wedded to that as the way to meet my goals.
Perhaps the best way would be to use -memprofile
and -memprofilerate=1
?
I suppose ultimately this issue/request could be phrased as:
Could there be something in the docs that says how to profile allocations?
as the current advice no longer works
Comment From: mknyszek
Perhaps the best way would be to use
-memprofile
and-memprofilerate=1
?
Ah hah, yes, this would also be an effective way of gathering the information you want. You'd get a stack trace at every allocation site.
Yes, we can update the documentation with this advice.