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

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.