This is an immersive long-form essay — best read in its dedicated layout → Open the full version
The eighth piece in the Field Note series, siblings to «The Life of One JS Line · QuickJS Source-Level Walkthrough» (one engine, full stack) and «How V8 makes JS fast» (multi-tier JIT). This one cuts across languages — how every modern runtime handles its dead.
Main line: one program, 11 families, 11 fates
let list = []
for i in 0..1_000_000:
list.push({ n: i })
list = null // ⭐ the moment of "many ways to die"
Those 17 characters behave radically differently across GCs:
- CPython refcount:
lst = Nonesynchronously frees 1M objects within ~28 ms. - Swift ARC: same-line free, but the programmer manually breaks cycles via
weak. - V8 Orinoco: nothing immediate — waits for the next minor GC (typically ~50ms later).
- JVM ZGC: concurrent — mark and compact in the background, app threads barely notice.
- Go: tri-color concurrent — cleaned at the next GC pacer fire.
- Erlang BEAM: GC runs per-process only — if this data is inside the actor, dies when the actor dies.
- Rust: dropped at compile time — no runtime GC exists.
11 families + 20+ implementations, all using the same code as the main line.
11 families
06 Refcount 07 Mark-Sweep 08 Copying · Cheney 09 Generational
10 Incremental 11 Concurrent 12 Region / per-actor 13 Colored ptr
14 No-GC 15 Hybrid 16 Academic
Every chapter answers the same 4 questions: when is memory freed, how long is the STW, how much CPU, what’s the heap shape after.
What this article digs into
- 11 fates of one line: CPython 28 ms synchronous vs ZGC 0.5 ms concurrent vs Erlang “dies with the process”.
- Real source from each family: from CPython’s
Py_DECREFto Go’sruntime/mgc.goto ZGC’sZBarrierto Erlang’sgc_minor. - 5 eternal tradeoffs: pause / throughput / memory / startup / mental overhead. No GC wins all 5.
- Production stories: Discord Go→Rust, Twitter Ruby→Scala, Pinterest Python tuning, LinkedIn JVM.
- Tuning decision tree: pick a GC by latency / throughput / memory / startup.
- 60-year family tree: 1959 McCarthy mark-sweep → 1969 Cheney copying → 1984 Lieberman generational → 2014 ZGC → 2023 Generational ZGC.
- What’s next: Carbon / Vale’s “linear GC” experiments, post-Rust ownership directions.
“McCarthy said in 1959: let programs manage memory themselves. Sixty-plus years later, we’re still debating how.”
Comments
0 comments