Reference Counting vs. Tracing GC
There are only two ways to decide an object is dead: count how many references point to it, or trace from the roots and see what's still reachable. This video puts reference counting and tracing side by side — the per-object counter decrement versus the mark phase, ARC versus a stop-the-world pause — and shows why the industry keeps switching between them.
Topics covered:
- Reference counting: increment on retain, decrement on release
- The cycle problem: why refcounting alone leaks self-referencing structures
- ARC: compile-time retain/release insertion and its overhead
- Tracing GC: the root set, the mark phase, and reachability as the definition of alive
- The pause: why tracing collects in batches and refcounting frees instantly
- Swift and Rust's choices: ownership moves vs. runtime counters
- Hybrids: Python's refcount plus a cycle detector
- The real trade-off: latency spikes vs. per-operation overhead and memory footprint
Related articles
How Garbage Collectors Decide What to Free
Mark-sweep, generational hypothesis, and GC pauses — the physics of automatic memory management and why it's never truly free.
Boxing, Unboxing, and Value vs Reference Semantics
Why every boxed int is a heap allocation, why int[] beats ArrayList and Integer[] by 4-16x, how Java generics erasure forces boxing, and how C# structs avoid it.
Branch Prediction and CPU Pipelines: Why Sorted Data Is Faster
How the branch target buffer, speculative execution, and pipeline flushes make sorted arrays up to 10x faster, and why __builtin_expect, retpolines, and Spectre mitigations exist.
More in Runtime & Execution
How Garbage Collection Actually Works
A visual walkthrough of mark-sweep, generational collection, and concurrent GC — the algorithms that keep your memory clean.
WatchWhat Your Code Does Before main()
The loader, the linker, the dynamic linker, and the runtime — everything that happens between pressing run and your first line of code.
WatchHow Threads Actually Work
The kernel scheduler, context switches, goroutines versus threads — a visual walkthrough of what 'running on a core' really means.
WatchAsync/Await Under the Hood
What async/await compiles to — state machines, continuations, and the executor — and how your async function actually runs on one or many threads.
DetailsVirtual Machines Explained
How language VMs like the JVM and the CLR work — bytecode verification, the execution engine, and the runtime services beneath your program.
DetailsInterpreters vs. Compilers
What an interpreter actually does at runtime versus what a compiler does before — ASTs, bytecode, and why the boundary keeps blurring.
DetailsStack vs. Heap Memory
Where your variables actually live — the hardware stack's push and pop discipline versus the heap's malloc and free — and why the difference matters.
DetailsThe Event Loop, Visualized
How Node.js and the browser run one thread with many tasks — the call stack, the task queue, and microtasks — animated frame by frame.
DetailsJIT Compilers Explained
How just-in-time compilers work — profiling, tiered compilation, and generating machine code at runtime — from interpreter to native in microseconds.
DetailsDepth, delivered weekly
One technical dispatch a week — articles and episode notes before they go public.
One technical dispatch per week. No noise.