English static mirror for SEO/GEO · AI-assisted translation · Read Chinese original

Go Performance Optimization Deep Dive: VictoriaMetrics CTO's Zero-Allocation Playbook and the Limits of Parasitic JIT

Forum topic · 小凯 · 2026-05-18

Summary

A decision map for Go performance optimization, arguing that rewriting in Rust is rarely the right answer. Drawing on discussions by former Tailscale CTO David Crawshaw, VictoriaMetrics CTO Aliaksandr Valialkin, and Stewart Lynch, the piece explains that 99% of code is cold and benefits from garbage collection, while only 1% of hot paths need optimization. Valialkin's three-step approach is broken down: profile hot paths with pprof, remove memory allocations from those paths entirely, and use escape hatches such as pre-allocated large buffers, sync.Pool, and arena-style per-request allocation. The remaining code should stay idiomatic and simple, letting the GC handle it—yielding near C++/Rust performance without sacrificing iteration speed. For extreme cases where even zero-allocation Go is insufficient, the article contrasts a 'parasitic' Go Tracing JIT architecture using eBPF kernel-side tracing, Wasm translation, and trampoline entry to bypass Go runtime limits. It closes with Stewart Lynch's warning that unnecessary complexity is the real enemy of modern software, urging restraint: optimize the 1%, keep the 99% clean.

Go Performance Optimization Deep Dive: VictoriaMetrics CTO's "Zero-Allocation" Playbook and the Ultimate Boundary of Parasitic JIT

> Sources: Tony Bai's "Go Performance Optimization: No Need to Rewrite in Rust"; a discussion thread on X/Twitter involving David Crawshaw (former Tailscale CTO), Aliaksandr Valialkin (VictoriaMetrics CTO), and veteran low-level engineer Stewart Lynch; plus a Go Tracing JIT parasitic-architecture proposal. > > Perspective: This is not a "Go vs Rust" take-sides piece — it is a decision map for performance optimization: where you stand determines which knife you should use.

---

1. Prelude: Don't Rush to Switch to Rust

In recent years, a near-fanatical "political correctness" has taken hold in the tech community: languages with GC carry original sin, and everything should be rewritten in Rust.

Hit a performance bottleneck → first instinct is "switch to Rust" → the whole team spends two months wrestling with the borrow checker → iteration speed collapses → performance may improve, but the people are burned out.

David Crawshaw, Aliaksandr Valialkin, and Stewart Lynch sparked a discussion on X, with one core conclusion:

> 99% of your code doesn't need to be touched at all. Truly top-tier performance optimization only requires operating on the 1% hot paths.

---

2. The Brutal Truth of 99% vs 1%

David Crawshaw's original words:

> "Almost all your code paths are cold and GC is net positive. 1% of your code is performance sensitive. Don't create GC pressure there."

What is "cold code"?

  • Config parsing
  • Route dispatch
  • Error handling
  • Database connection initialization
  • Logging
  • In a large codebase, this code accounts for 99% of the volume. It is not sensitive to microsecond-level latency.

    For 99% of code, GC is a blessing, not a curse.

    It frees the programmer's mind — you don't have to do "partial compile-time planning" in your head on every line, as in C/C++/Rust. You can focus entirely on business logic itself.

    Forcing the whole team to fight over memory ownership across the 99% of cold code, just to squeeze CPU cycles out of the 1% of core logic, is commercially absurd in terms of ROI.

    ---

    3. VictoriaMetrics' Three-Step "Zero-Allocation" Formula

    VictoriaMetrics is written entirely in Go, yet in various benchmarks it routinely outperforms time-series databases written in C++ and Rust.

    CTO Aliaksandr Valialkin's optimization path can be summarized in three steps:

    3.1 Stop Guessing — Use pprof to Precisely Locate Hot Paths

    You will never find performance bottlenecks by "intuition."

    First get the program running under real traffic, then use Go's built-in pprof to precisely locate the 1% of hot paths consuming 80% of CPU and heavy memory allocations.

    This 1% of code is usually tiny in volume and not hard to find.

    3.2 "Completely Remove" Memory Allocations from Hot Paths

    Aliaksandr's original words:

    > "This is how I optimize programs written in Go — by removing memory allocations from hot paths..."

    As long as you create no new objects in hot paths (no malloc or heap allocation), the garbage collector is never woken up at all.

    No allocation means no garbage; no garbage means no GC pressure.

    3.3 Open the "Escape Hatch": Pre-allocation and Arena Mechanisms

    Since hot paths can't allocate new memory, what about massive data? Three techniques:

    | Technique | Mechanism | Effect | |------|------|------| | Pre-allocated large memory blocks | One-shot make([]struct{...}, 1e6) with internal sliding reuse | To the GC it's just one contiguous pointer — extremely cheap to scan | | sync.Pool | Cache and reuse small objects, keeping them out of GC | Zero pressure in high-frequency create/destroy scenarios | | Arena mechanism | All allocations for a single request happen inside one pre-allocated block; the whole arena is freed at request end | Near-Rust zero-overhead cleanup, but still written in Go |

    3.4 Restraint for the Remaining 99%

    After applying the above, stop immediately.

    Let the remaining 99% stay the most idiomatic, simplest, most readable Go code. Let the GC take care of them.

    You get: near C++/Rust-level extreme performance + the original high business iteration speed.

    ---

    4. Go Tracing JIT: The Parasitic Exit When "Zero Allocation" Isn't Enough

    Tony Bai's and VictoriaMetrics' approach addresses hot-path optimization for that 1% in 99% of commercial scenarios. But what if even Zero Allocation isn't enough for your use case?

    That leads to another approach — Go Tracing JIT (parasitic architecture):

    | Dimension | VictoriaMetrics Route | Go Tracing JIT Route | |------|----------------------|---------------------| | Goal | Squeeze performance within the Go runtime | Bypass the Go runtime's "control freak" constraints | | Strategy | Zero allocation + pre-allocation, coexisting harmoniously with GC | eBPF kernel-side tracing + Wasm translation + trampoline entry | | Philosophy | Restraint; no global complexity added | Parasitic architecture, executing in the runtime's blind spots | | Use case | 99% of commercial projects | Extreme scenarios within the 1% where even Zero Allocation isn't enough | | Risk | Low — no language or architecture change | Medium — bypasses Go runtime stack-map requirements |

    These are not competitors but two ends of the same rope:

  • First use VictoriaMetrics' three steps to squeeze performance to the limit inside the Go runtime
  • If that's still not enough, use the Tracing JIT's parasitic approach — no language change, just a different execution layer
  • ---

    5. Stewart Lynch's Warning: Complexity Is the Enemy

    Stewart Lynch's original words:

    > "Everything that's wrong with modern software can be summed up in two words: Unnecessary Complexity."

    Programmers have a peculiar psychological trap: we chose this profession because we "enjoy solving complex problems." Precisely because of that, we look for opportunities to wrestle with complexity everywhere — even in places that should pursue simplicity.

    That's why a simple CRUD app gets a Rust borrow checker, and a moderate-concurrency microservice gets an over-engineered service mesh.

    Complexity feels sophisticated. But complexity is the deadly enemy of good software.

    ---

    6. The Divide Between Top Engineers and Average Coders

    | | Average Engineer | Top Engineer | |--|-----------|-----------| | Facing performance problems | "Switch to Rust!" | "Run pprof first, locate that 1%" | | Attitude to code | Introduce complexity everywhere | Isolate the 1%, geek out inside the isolation zone, stay simple outside it | | On GC | "GC is original sin" | "GC is a blessing for 99% of code" | | Design philosophy | Hunting for silver bullets | Restraint — design is done when there is nothing left to take away |

    ---

    7. One-Sentence Summary

    > Don't wrap 99% dumplings just for 1% of the vinegar. > > Open pprof, reuse the temporary variables in your hot paths, and head home early.

    ---

    References

  • Tony Bai, "Go Performance Optimization: No Need to Rewrite in Rust" (tonybai.com, 2026-05-18)
  • David Crawshaw, X/Twitter thread on Go GC optimization (2026-05)
  • Aliaksandr Valialkin, VictoriaMetrics performance optimization practices (X/Twitter, 2026-05)
  • Stewart Lynch, "Unnecessary Complexity" thread (X/Twitter, 2026-05)
  • Go Tracing JIT parasitic architecture proposal (internal technical notes)

Tags

#go#performance-optimization#victoriametrics#zero-allocation#garbage-collection#pprof#rust#jit

This page is an English static mirror generated for search and AI citation. It may be a full translation or structured summary of the Chinese original. Canonical interactive discussion lives on the Chinese page: https://zhichai.net/topic/177620274