RepoFlow Team · Aug 10, 2026

Go 1.19 to 1.26 Benchmarks: How Performance Evolved Over Time

Synthetic application throughput, latency, GC, CPU and memory, plus eight focused microbenchmarks across eight Go releases.

After publishing several version-to-version runtime benchmarks, we received a lot of requests to test Go next.

So we continued the series with the latest patch releases of Go 1.19 through Go 1.26. We measured a sustained synthetic application alongside focused microbenchmarks to see how throughput, latency, garbage collection, CPU use, memory use, and common hot paths evolved across releases.

Versions tested

We tested official Go Docker images at these exact patch releases:

  1. Go 1.19.13 (golang:1.19.13)
  2. Go 1.20.14 (golang:1.20.14)
  3. Go 1.21.13 (golang:1.21.13)
  4. Go 1.22.12 (golang:1.22.12)
  5. Go 1.23.12 (golang:1.23.12)
  6. Go 1.24.13 (golang:1.24.13)
  7. Go 1.25.12 (golang:1.25.12)
  8. Go 1.26.5 (golang:1.26.5)

Every image passed the benchmark self-test and test suite before measurement.

What the synthetic application does

The application combines work that appears in ordinary services: scanning fields in a deterministic 1,024-byte JSON payload, SHA-256 hashing, a sharded bounded cache, Base64 encoding, and 256 bytes of allocation pressure per operation. A pool of 1,024 payloads keeps the input stable while 10 worker goroutines run against 10 available container processors.

Each application process warmed up for 20 seconds and then measured for 600 seconds. We repeated each Go-version and memory-profile combination in five isolated processes.

Synthetic application results

The charts compare GOMEMLIMIT targets of 512MiB, 2GiB, and 4GiB. This setting guides garbage collection rather than reserving a fixed-size heap, and the workload remained below even the smallest target, so minor differences between profiles should be treated as run-to-run variation.

Throughput

Average throughput in millions of operations per second across five repeats.

Higher is better

Mean latency

Average per-operation latency in microseconds across five repeats.

Lower is better

Total GC pause time

Average total garbage-collection pause time during the measurement window.

Lower is better

CPU use

Average process CPU utilization as a percentage of all available cores.

Lower is better

Resident memory

Average resident set size in MiB.

Lower is better

Go heap memory

Average live Go heap memory in MiB.

Lower is better

Go Sys memory

Average memory obtained from the operating system by the Go runtime.

Lower is better

Application behavior over time

These 4GiB charts include all eight Go versions and use 60-second points from the recorded per-second series. Each point is the median across the five repeats.

Heap over time

Go heap memory in MiB during the 10-minute measurement window.

Lower is better
Smoothing window Smooths the line using a centered moving average across nearby minutes. 1m shows raw values.

RSS over time

Resident set size in MiB during measurement.

Lower is better
Smoothing window

Go Sys over time

Memory obtained from the operating system by the Go runtime during measurement.

Lower is better
Smoothing window

CPU over time

Process CPU utilization as a percentage of all cores during measurement.

Lower is better
Smoothing window

Microbenchmark results

Each focused benchmark used a 5-second warmup, a 10-second measurement, and five isolated process repeats. The charts show the 4GiB profile so the version trend stays readable, the 512MiB and 2GiB results followed the same broad story.

JSON parsing

Repeated parsing of the deterministic 1,024-byte JSON payload.

Higher is better

JSON encoding

Repeated serialization of the benchmark object to JSON.

Higher is better

SHA-256

Repeated SHA-256 digest calculation on the same payload size.

Higher is better

Base64 encoding

Repeated Base64 encoding and decoding on the same payload size.

Higher is better

Regular expressions

Repeated field matching in a short string using a regular expression.

Higher is better

Integer sorting

Repeated sorting of an integer slice.

Higher is better

Concurrent map churn

High-churn concurrent map read and write workload.

Higher is better

Deflate compression

Repeated Deflate compression on the same payload size.

Higher is better

How the tests were performed

  • Host: Apple M4, 10 cores, 16 GiB RAM
  • OS: Darwin 26.3, Docker 29.1.3
  • Runtime: official Go images, latest patch of Go 1.19 through 1.26
  • Profiles: GOMEMLIMIT=512MiB, 2GiB, and 4GiB, then GOGC=100
  • Concurrency: 10 worker goroutines and 10 available container processors
  • Synthetic app: 20-second warmup, 600-second measurement, five isolated repeats
  • Microbenchmarks: 5-second warmup, 10-second measurement, five isolated repeats
  • Summary metrics: arithmetic means across the five repeats
  • Time-series metrics: per-second medians across the same repeats

Source code

Conclusion

These results show why runtime upgrades are worth measuring with more than one headline number. An overall application and its individual hot paths do not always move together, and the differences that matter depend on where a real service spends its time.

Before upgrading, benchmark the request paths, allocation patterns, and library operations that matter to your application. The charts above are a reference point, not a substitute for testing your own workload.

Which Go workload should we put through the suite next? Send us your ideas.
Happy Benchmark Monday!

Join our mailing list

Product updates, new tools, and practical guides from RepoFlow.