chapter nine

9 Garbage Collection

 

This chapter covers

  • Seeing what follows from the spec's silence on garbage collection
  • Tracing V8's generational Orinoco collector
  • Comparing V8’s garbage collection to JSC's non-moving Riptide collector
  • Spotting allocation patterns that cause GC thrashing
  • Releasing references safely with WeakRef, WeakMap, and FinalizationRegistry

So far, we’ve hand waved around memory management. We’re going to fix that now.

We've seen how microtasks, macrotasks, and rendering callbacks compete for the main thread. The garbage collector is competing for it too, and it's the one most developers forget about.

JavaScript developers often treat memory like a hotel room: You check in, use whatever you want, and someone else cleans up after you leave. You've probably heard that analogy before. What it leaves out is that the cleaning crew doesn't wait until you check out.

For instance, a Node.js server handling server-side rendering for a React application is running under steady traffic. The code works perfectly and is as tuned for performance as a React application can be. However, every few seconds, response times spike by hundreds of milliseconds for no apparent reason. Database latency is fine, the network is clean, and your logging shows that nothing is going wrong. The spikes come and go seemingly without explanation.

9.1 The basics of garbage collection

9.1.1 Clarifying the null misconception

9.2 Getting generational

9.2.1 V8's heap layout

9.2.2 The Scavenger

9.2.3 Mark-Sweep-Compact

9.2.4 Write barriers and remembered sets

9.3 How JavaScriptCore does it differently

9.3.1 No semi-spaces, no copying

9.3.2 Sticky mark bits

9.3.3 The retreating wavefront

9.3.4 Concurrent marking and the death spiral problem

9.3.5 Lazy sweeping through logical versioning

9.3.6 Orinoco and Riptide, side-by-side

9.4 When the garbage collection bites

9.4.1 Allocation patterns that compound

9.4.2 What you can do about it

9.5 WeakSets and WeakMaps

9.6 FinalizationRegistry and WeakRefs

9.7 What the specification left you

9.8 Summary