Go Performance Optimization Deep Dive: VictoriaMetrics' "Zero-Allocation" Playbook and the Ultimate Limits of Parasitic JIT
> Sources: Tony Bai's "Go Performance Optimization: No Need to Rewrite in Rust"; discussion threads on X/Twitter involving David Crawshaw (former Tailscale CTO), Aliaksandr Valialkin (VictoriaMetrics CTO), and Stewart Lynch (low-level code veteran); the Go Tracing JIT parasitic architecture proposal. > > Perspective: This is not a "Go vs Rust" tribal post, but a decision map for performance optimization — where you stand determines which tool you use.
1. Don't Rush to Rewrite in Rust
In recent years, a near-fanatic "political correctness" has swept tech communities: GC languages carry original sin, and everything should be rewritten in Rust.
Hit a performance bottleneck → first instinct: "rewrite in Rust" → the whole team struggles with the borrow checker for two months → iteration speed collapses → performance may improve, but the team is 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 any of this. Truly top-tier performance optimization only requires operating on the 1% of hot paths.
2. The Brutal Truth of 99% vs 1%
David Crawshaw's exact 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"?
- Configuration parsing
- Route dispatching
- Error handling
- Database connection initialization
- Logging
- First use the VictoriaMetrics three-step method to extract maximum performance within the Go runtime.
- If that's still not enough, use the Tracing JIT's parasitic approach — no language change needed, just a different execution layer.
- 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 record)
In a large codebase, this code makes up 99% of the volume. It is entirely insensitive to microsecond-level latency.
GC is a blessing for 99% of code, not a curse.
It frees programmers' minds from mentally "compile-time planning" every line like you would in C/C++/Rust, letting you focus entirely on business logic. Forcing the whole team to fight over memory ownership in the 99% of cold code just to squeeze CPU cycles out of the 1% core logic is commercially absurd in terms of ROI.
3. VictoriaMetrics' Three-Step "Zero-Allocation" Playbook
VictoriaMetrics is written entirely in Go, yet in many benchmarks it beats time-series databases written in C++ and Rust.
CTO Aliaksandr Valialkin's optimization approach 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 identify the 1% of hot paths consuming 80% of CPU and heavy memory allocations. This 1% is usually tiny in code volume — not hard to find.
3.2 "Completely Remove" Allocations in Hot Paths
Aliaksandr's words:
> "This is how I optimize programs written in Go — by removing memory allocations from hot paths..."
As long as you don't create new objects in hot paths (no malloc, no heap allocation), the garbage collector never wakes up.
No allocation means no garbage; no garbage means no GC pressure.
3.3 The "Escape Hatch": Pre-allocation and Arena Mechanisms
If 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 | Appears to GC as a single contiguous pointer with minimal scan cost |
| sync.Pool | Caches and reuses small objects, keeping them out of GC | Zero pressure for high-frequency create/destroy scenarios |
| Arena mechanism | All allocations for a single request happen in 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 Other 99%
After applying these techniques, stop immediately.
Let the remaining 99% stay the most idiomatic, simplest, most readable Go code. Let the GC take care of it.
The result: performance rivaling C++/Rust, plus the original high business iteration speed.
4. Go Tracing JIT: The Parasitic Exit When "Zero Allocation" Isn't Enough
The Tony Bai / VictoriaMetrics approach solves hot-path optimization within 99% of commercial scenarios. But what if even Zero Allocation isn't enough for your use case?
This leads to the Go Tracing JIT (parasitic architecture) approach:
| Dimension | VictoriaMetrics Route | Go Tracing JIT Route | |------|----------------------|---------------------| | Goal | Squeeze maximum performance within the Go runtime | Bypass the Go runtime's "control freak" constraints | | Strategy | Zero allocation + pre-allocation, coexisting peacefully with GC | eBPF kernel-side tracing + Wasm translation + trampoline entry | | Philosophy | Restraint; no added global complexity | Parasitic architecture, executing in the runtime's blind spots | | Use case | 99% of commercial projects | The extreme 1% where even Zero Allocation isn't enough | | Risk | Low — no language or architecture changes | Medium — bypasses Go runtime stack-map requirements |
The two are not competitors, but two ends of the same rope:
5. Stewart Lynch's Warning: Complexity Is the Enemy
Stewart Lynch's exact words:
> "Everything that's wrong with modern software can be summed up in two words: Unnecessary Complexity."
Programmers have a particular psychological trap: we chose this profession because we "enjoy solving complex problems." Precisely because of that, we look for chances to wrestle with complexity everywhere — even in places where simplicity should be the goal.
That's why a simple CRUD app adopts Rust's borrow checker, and a moderately concurrent microservice gets an over-engineered service mesh.
Complexity feels sophisticated. But complexity is the enemy of good software.
6. The Divide Between Top Engineers and Average Coders
| | Average Engineer | Top Engineer | |--|-----------|-----------| | Facing performance issues | "Rewrite in Rust!" | "pprof first, locate that 1%" | | Attitude toward code | Introduce complexity globally | Isolate the 1%, geek out inside the isolation zone, stay simple outside | | On GC | "GC is original sin" | "GC is a blessing for 99% of code" | | Design philosophy | Hunt for silver bullets | Restraint — design is complete when there's nothing left to take away |
7. One-Sentence Summary
> Don't wrap 99% dumplings just for 1% of the vinegar. > > Open pprof, reuse the temporaries in your hot paths, and head home early.