tgc design notes
This page is the canonical design reference for tgc.
Earlier blog drafts used “v1 / Phase 2” wording; that split is retired.
Current code: 0.2.3 (see _d_tgc_version()).
Versioning (SemVer pre-1.0)
| Version | Kind | Scope |
|---|---|---|
0.1.0 |
First prototype |
Per-thread private heaps, local collect, remote-free stub. No region API. |
0.1.1 |
Patch |
Region API scaffold only (no region collect). |
0.2.0 |
Feature / breaking milestone |
Region collect with selective suspend, heap list locks, array append metadata, tests + benchmark harness. |
0.2.1 |
Patch |
Sorted-address |
0.2.2 |
Patch |
Layered pointer lookup (range reject, linear for tiny heaps, binary otherwise), bulk index shifts, tri-state fixpoint marking, full stack/TLS scanning, corrected append metadata, and an explicit remote-free test. |
0.2.3 (current) |
Patch |
Exact-base API conformance, race-safe duplicate-coalescing remote frees, overflow checks, terminating worklist-style marking, serialized region collection, suspension lock barriers, and private-heap-to-region reachability. |
0.3.0 (planned) |
Opt-in feature |
SymGC-backed shared regions via |
Bump rules (short)
-
Pure bugfix (wrong collect, race, crash) →
0.1.zpatch. -
Non-breaking improvement (perf, better
findBlock, docs, additive API with no behavior change) →0.1.zpatch. -
Breaking change (cross-thread contract, default alloc routing, removing remote-free, region collect that changes pause guarantees) →
0.y.0minor bump. -
SymGC + tgc hybrid: not breaking if it is a new opt-in gcopt flag and default
gc:tgcmatches prior minor; breaking if existing region or private-heap behavior changes without opt-in → bump with the feature that changes defaults.
Problem statement
D isolates data by default (TLS, actor-style std.concurrency) but the default GC uses one process-wide heap.
Any collection can stop-the-world pause every registered thread, including @nogc realtime workers that never allocate.
The goal is pause isolation: threads that do not depend on the same GC data should not pause each other.
Target architecture (the actual design)
Per-thread private heap
Every attached thread owns a private arena. Collection scans only that thread’s stack, TLS, roots, and blocks in its private heap. No global STW for a pure local collect.
Partitioned shared regions (core cross-thread model)
Cross-thread data is not modeled as “copy everything” or “remote free on the owning thread’s private heap.” Those are interim or escape-hatch paths only.
The intended model is partitioned shared regions:
-
A region is a GC heap shared by an explicit set of threads (many-to-many).
-
Threads opt in to regions that match their data dependency and lifetime.
-
Collecting region Alpha pauses only threads attached to Alpha, not the whole process.
-
A thread with only a private heap and no shared regions is never paused by another region’s collection.
SymGC hybrid (future, inside gc:tgc)
One registered factory (gc:tgc), not two GCs in one process.
Private heaps stay tgc-local; shared regions may use a SymGC-derived allocator/collector backend for the shared slice only.
Requires extracting or cooperating with SymGC — not linking gc:sdc and gc:tgc as separate active collectors.
What ships today
0.1.0
-
--DRT-gcopt=gc:tgc -
Local collect on private per-thread heap
-
Remote-free queue on private heaps (implemented, but interim to the region model)
0.2.0 adds
-
_d_tgc_region_collectwith selective thread suspend (thread_suspendList) -
Per-heap list locks; basic array append metadata
-
Tests:
tgc_regions.d; benchmark:tgc_bench.d+tools/tgc-bench/run-benchmarks.ps1 -
Demo page: tgc demo
Pluggable GC and SymGC
druntime selects one GC implementation at process startup (--DRT-gcopt=gc:…).
Per-branch mixing of gc:sdc and gc:tgc is not supported without a composite gc:tgc implementation.
Source material on disk
-
Forum draft:
AMDphreak/.issues/forum-tgc-thread-local-gc.md -
Agent plan:
tgc_opt-in_upstream_bfb2d23a.plan.md(machine-local Cursor plans)
Upstream
-
PR: https://github.com/dlang/dmd/pull/23514unchecked
-
Branch:
feature/tgcunchecked