Maximizing Go Performance with the Green Tea Garbage Collector: A Hands-On Tutorial
<h2 id="overview">Overview</h2>
<p>Garbage collection (GC) is a double‑edged sword: it frees developers from manual memory management, but runtime overhead can slow down applications. The Go team has introduced an experimental garbage collector named <strong>Green Tea</strong> in Go 1.25. Benchmarks show that many workloads spend 10–40% less time in the GC, with production deployments at Google already reaping the benefits. This tutorial will guide you through enabling, testing, and evaluating Green Tea in your own projects. By the end, you’ll know how to leverage this new collector to reduce pause times and improve throughput, and you’ll understand how to provide valuable feedback to the Go team.</p><figure style="margin:20px 0"><img src="greenteagc/marksweep-007.png" alt="Maximizing Go Performance with the Green Tea Garbage Collector: A Hands-On Tutorial" style="width:100%;height:auto;border-radius:8px" loading="lazy"><figcaption style="font-size:12px;color:#666;margin-top:5px">Source: blog.golang.org</figcaption></figure>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li><strong>Go 1.25 or later</strong> – Green Tea is experimental in 1.25 and will become default in 1.26. Download the latest release from <a href="https://go.dev/dl/" target="_blank" rel="noopener">go.dev/dl</a>.</li>
<li><strong>A Go project</strong> that allocates heap memory (most real‑world programs do). A simple web server, CLI tool, or data pipeline works well.</li>
<li><strong>Basic familiarity with the Go build toolchain</strong> – you should know how to set environment variables and run <code>go build</code>.</li>
<li><strong>Benchmarking tools</strong> – <code>benchstat</code> or simple shell timers to compare before/after results.</li>
</ul>
<h2 id="step-by-step">Step‑by‑Step Instructions</h2>
<h3 id="1-enable-green-tea">1. Enable Green Tea at Build Time</h3>
<p>Add the <code>GOEXPERIMENT=greenteagc</code> environment variable when building your application. There are two common ways:</p>
<pre><code># Approach A: Set per command
GOEXPERIMENT=greenteagc go build -o myapp .
# Approach B: Export in your shell (persistent for the session)
export GOEXPERIMENT=greenteagc
go build -o myapp .</code></pre>
<p><strong>Note:</strong> The environment variable must be set <em>at build time</em>, not at runtime. Once the binary is built, it will always use the chosen collector.</p>
<h3 id="2-verify-the-build">2. Verify the Build</h3>
<p>Check which collector your binary is using by running:</p>
<pre><code>go version -m myapp | grep GOEXPERIMENT</code></pre>
<p>If you see <code>GOEXPERIMENT=greenteagc</code>, you’re good. Otherwise, rebuild with the variable set.</p>
<h3 id="3-run-your-application">3. Run Your Application</h3>
<p>Launch your binary as you normally would. No runtime flags are needed. Monitor GC activity using the <code>GODEBUG=gctrace=1</code> environment variable to see detailed GC logs:</p>
<pre><code>GODEBUG=gctrace=1 ./myapp</code></pre>
<p>This prints lines like:</p>
<pre><code>gc 1 @0.024s 2%: 0.008+0.50+0.012 ms clock, 0.016+0.20/0.40/0.20+0.024 ms cpu, 4->4->0 MB, 5 MB goal, 8 P</code></pre>
<p>Pay attention to the <em>total GC CPU time</em> (the first percentage and the numbers after <code>cpu</code>).</p>
<h3 id="4-benchmark-with-and-without-green-tea">4. Benchmark With and Without Green Tea</h3>
<p>To measure improvement, build two binaries – one with the default GC and one with Green Tea – and compare them under identical workload.</p>
<ol>
<li>Build the baseline binary (without <code>GOEXPERIMENT</code>):<br><code>go build -o myapp-default .</code></li>
<li>Build the Green Tea binary:<br><code>GOEXPERIMENT=greenteagc go build -o myapp-greentea .</code></li>
<li>Run a realistic load test against each. For example, use <code>wrk</code> for HTTP servers or <code>time</code> for a CLI tool.</li>
</ol>
<p><strong>Example with a web server:</strong></p>
<pre><code># Baseline
./myapp-default &
PID=$!
wrk -t4 -c100 -d30s http://localhost:8080
kill $PID
# Green Tea
./myapp-greentea &
PID=$!
wrk -t4 -c100 -d30s http://localhost:8080
kill $PID</code></pre>
<p>Record the latency percentiles and request rate. Typically, Green Tea reduces GC pauses and improves tail latency.</p><figure style="margin:20px 0"><img src="https://go.dev/images/google-white.png" alt="Maximizing Go Performance with the Green Tea Garbage Collector: A Hands-On Tutorial" style="width:100%;height:auto;border-radius:8px" loading="lazy"><figcaption style="font-size:12px;color:#666;margin-top:5px">Source: blog.golang.org</figcaption></figure>
<h3 id="5-analyze-gctrace-output">5. Analyze gctrace Output</h3>
<p>For deeper analysis, capture GC traces from both runs and compare the total GC CPU time. A quick script to sum the CPU percentages:</p>
<pre><code>GODEBUG=gctrace=1 ./myapp 2>&1 >/dev/null | grep 'gc ' | awk '{print $3}' | sed 's/%//' | awk '{sum+=$1} END {print sum}'</code></pre>
<p>This prints the cumulative percentage of CPU spent in GC. Green Tea should show a lower number for memory‑intensive workloads.</p>
<h3 id="6-provide-feedback">6. Provide Feedback</h3>
<p>If you see improvements, <a href="https://github.com/golang/go/issues/69416" target="_blank" rel="noopener">post your success on the existing Green Tea issue</a>. If you encounter problems (regressions, panics, unexpected behavior), <a href="https://github.com/golang/go/issues/new" target="_blank" rel="noopener">file a new issue</a> with details about your workload, hardware, and any error messages.</p>
<h2 id="common-mistakes">Common Mistakes</h2>
<ul>
<li><strong>Setting <code>GOEXPERIMENT</code> at runtime</strong> – The environment variable must be present during <code>go build</code>. Adding it at execution time has no effect.</li>
<li><strong>Building with an older Go version</strong> – Green Tea is only available in Go 1.25+. Verify your Go version with <code>go version</code>.</li>
<li><strong>Misleading benchmarks</strong> – If your workload is CPU‑bound and barely allocates, Green Tea may show no improvement. Focus on allocation‑intensive workloads.</li>
<li><strong>Forgetting to rebuild after changing <code>GOEXPERIMENT</code></strong> – The binary caches the collector choice. Always rebuild when toggling the flag.</li>
<li><strong>Ignoring the <code>gctrace</code> percentage</strong> – A 1% reduction in GC time may be within noise. Run multiple iterations and use statistical tools like <code>benchstat</code>.</li>
</ul>
<h2 id="summary">Summary</h2>
<p>Green Tea is a promising evolution of the Go garbage collector that reduces GC overhead significantly for many real‑world programs. By following this tutorial, you’ve learned how to enable it at build time, verify its usage, benchmark your application, and interpret the results. Remember that it is experimental in Go 1.25 and feedback is essential for its path to becoming the default in Go 1.26. Try it on your own projects, share your findings, and help the Go community deliver faster, more efficient applications.</p>
Tags: