This is the second in a three part series exploring the performance improvements in the recent Go 1.1 release.
In part 1 I explored the improvements on
amd64 platforms, as well as general improvements available to all via runtime and compiler frontend improvements.
In this article I will focus on the performance of Go 1.1 on
386 machines. The results in this article are taken from linux-386-d5666bad617d-vs-e570c2daeaca.txt.
Go 1 benchmarks on
When it comes to performance, the
8g compiler is at a disadvantage. The small number of general purpose registers available in the
386 programming model, and the weird restrictions on their use place a heavy burden on the compiler and optimiser. However that did not stop Rémy Oudompheng making several significant contributions to
8g during the 1.1 cycle.
Firstly the odd
387 floating point model was deprecated (it’s still there if you are running very old hardware with the
GO386=387 switch) in favor of SSE2 instructions.
Secondly, Rémy put significant effort into porting code generation improvements from
arm compiler). Where possible code was moved into the compiler frontend,
gc, including introducing a framework to rewrite division as simpler shift and multiply operations.
In general the results for
linux/386 on this host show improvements that are as good, or in some cases, better than
linux/amd64, there is no slowdown in the
The two small regressions,
Fannkuch11, are assumed to be attributable to the garbage collector becoming more precise. This involves some additional bookkeeping to track the size and type of objects allocated on the heap, which shows up in these benchmarks.
The improvements in the
net package previously demonstrated in the
linux/amd64 article carry over to
linux/386. The improvements in the
ClientServer benchmarks are not as marked as its
amd64 cousin, but nonetheless show a significant improvement overall due to the tighter integration between the
amd64 benchmarks in part 1, the
runtime microbenchmarks show a mixture of results. Some low level operations got a bit slower, while other operations, like
map have improved significantly.
The final two benchmarks, which appear truncated, are actually so large they do not fit on the screen. The improvement is mostly due to this change which introduced a faster low level
Equals operation for the
runtime packages. The results speak for themselves.
benchmark old MB/s new MB/s speedup BenchmarkCompareStringBigUnaligned 29.08 1145.48 39.39x BenchmarkCompareStringBig 29.09 1253.48 43.09x
8g is not the leading compiler of the gc suite, Ken Thompson himself has said that there are essentially no free registers available on
linux/386 shows that it easily meets the 30-40% performance improvement claim. In some benchmarks, compared to Go 1.0,
Additionally, due to reductions in memory usage, all the compilers now use around half as much memory when compiling, and as a direct consequence, compile up to 30% faster than their 1.0 predecessors.
I encourage you to review the benchmark data in the autobench repository and if you are able, submit your own results.
In the final article in this series I will investigate the performance improvement Go 1.1 brings to
arm platforms. I assure you, I’ve saved the best til last.
Update: thanks to @ajstarks who provided me with higher quality benchviz images.