2

How does one uses environment variables to optimize a go binary?

For instance, with C and GCC, you would set CFLAGS="-O2 -march=znver1 to build with tier 2 optimizations, with specific optimizations for the Zen microarchitecture. I couldn't find an equivalent environment variable in Golang's documentation.

Go does provide a way to disable them all, but not to specify which one to use in case you are using gccgo as the compiler back-end. It is thus very different from other questions asked about optimizations flags for Go in general (Passing an optimization flag to a Go compiler? for instance)

Antoine Viallon
  • 314
  • 4
  • 12
  • 4
    Go's compiler does not have optimization levels (only the option to disable optimization, which is enabled by default), and optimizations are done for the architecture the build is targeting, no greater specificity is available. – Adrian Oct 08 '20 at 18:30
  • Oh, I didn't know about that! Also, I saw somewhere that if building with gccgo, you could add optimizations. Am I correct? – Antoine Viallon Oct 09 '20 at 11:33
  • @Adrian GCC-GO can actually optimize builds for a specific architecture, since it uses GCC's backend. – Antoine Viallon Feb 20 '21 at 15:16

1 Answers1

7

After searching for a very long while, I found the information I needed. First of all, as Adrian mentionned, the standard gc compiler (which is usually the most up-to-date regarding the Go spec), does not support optimization flags (except for disabling them completely using -N -l as mentionned here).

However, if you use GCCGO, there is an environment variable you can use, which is GOGCCFLAGS. Using go env on my system with gcc-go installed, I saw that its default value was -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build920233973=/tmp/go-build -gno-record-gcc-switches -funwind-tables. One can thus override this environment variable and pass other optimizations, like those described in GCCGO's documentation. Standard gcc options seems to work, like -march=native for instance, which is exactly what I was searching for.

Edit: after more testing, it seems that Go often ignores this environment variable, so you have to add -gccgoflags="${GOGCCFLAGS}".

Edit 25/01/2022: Since Go 1.18, the GOAMD64 environment variable was added, allowing you to choose a target x86_64 feature-level (from v1 to v4). The default is GOAMD64=v1, but if you know you'll only target CPUs newer than Sandy Brige or Bulldozer, you can safely use GOAMD64=v2 to gain some performance.

A similar environment variable exists for ARM. You can have more details here: https://github.com/golang/go/wiki/MinimumRequirements#microarchitecture-support

Antoine Viallon
  • 314
  • 4
  • 12