
February 23, 2026
Ruby has traditionally shipped with a single, built-in garbage collector tightly coupled to the VM. With Ruby 3.4, that assumption begins to change.
Feature #20470 introduces an experimental Modular Garbage Collector API, allowing CRuby to load alternative GC implementations at runtime. This marks one of the most significant architectural shifts in Ruby’s memory management since the introduction of generational GC.
Instead of a fixed collector, Ruby is moving toward a future where garbage collection becomes a replaceable component.
🔌 From Monolithic GC to Pluggable Architecture
Historically, CRuby’s garbage collector was inseparable from the interpreter:
Ruby VM (YARV) └── Built-in GC
With the modular system:
Ruby VM ├── GC Interface (stable API) └── GC Implementation (loadable module)
Garbage collectors are now built as dynamic libraries and loaded at runtime. Ruby communicates with them through a defined interface (gc_impl.h), decoupling memory management from the VM core.
This change enables experimentation without forking Ruby itself.
⚙️ How Modular GC Works
A modular collector is compiled as a shared library:
librubygc.<name>.so
Ruby selects the implementation via an environment variable:
RUBY_GC_LIBRARY=default ruby app.rb
Or an alternative implementation:
RUBY_GC_LIBRARY=mmtk ruby app.rb
Internally, Ruby loads the library using dynamic linking and delegates allocation and collection responsibilities to it.
🧪 Built-In Options: Default GC and MMTk
Ruby 3.4 ships with two implementations:
✔ Default GC (modularized)
The traditional CRuby collector:
- Generational mark-and-sweep
- Incremental marking
- Optional compaction
- Mature and production-ready
It can now run either built-in or as a module.
✔ Experimental MMTk-Based GC
Ruby also includes a collector implemented using the Memory Management Toolkit (MMTk), a research framework designed for building modern garbage collectors.
MMTk supports advanced algorithms such as:
- Immix (region-based, low fragmentation)
- Concurrent collectors
- Various heap policies
Although experimental, it demonstrates that Ruby can integrate sophisticated memory management strategies without rewriting the VM.
🧩 What a GC Implementation Must Handle
Implementing a Ruby GC is extremely complex. A replacement collector must coordinate with the VM at a deep level, including:
- Object allocation
- Heap organization
- Root scanning (stack, globals, registers)
- Marking reachable objects
- Reclaiming unused memory
- Write barriers for generational correctness
- Finalizers
- Interaction with C extensions
- Ractors and thread safety
- Optional object compaction
Because Ruby objects are exposed to C extensions, moving them safely is particularly challenging.
🔍 Inspecting the Active GC
Ruby 3.4 introduces ways to query the active implementation:
GC.config[:implementation]# => "default" or "mmtk"
This reflects the modular GC currently in use.
🚀 Why This Matters
Even in experimental form, modular GC fundamentally changes Ruby’s trajectory.
🧠 Faster Innovation
New algorithms can be developed independently of the VM, enabling rapid experimentation without destabilizing CRuby.
🌐 Adaptation to New Environments
Different workloads require different memory strategies. Modular GC opens the door to collectors optimized for:
- Serverless runtimes
- Short-lived CLI tools
- WebAssembly environments
- Embedded systems
- High-throughput servers
- Low-latency applications
⚡ Potential for Concurrent or Pauseless GC
Modern languages increasingly rely on collectors that minimize pause times. A pluggable architecture allows Ruby to explore such designs incrementally.
🔬 Research and Benchmarking
Multiple collectors can be compared under identical conditions, accelerating both academic and practical research into Ruby performance.
⚠️ Current Status
The modular GC system is experimental:
- Not enabled by default
- Requires building Ruby with modular GC support
- Not widely packaged in distribution builds
- Alternative collectors are not production-ready
However, the infrastructure is real and evolving.
🔮 A Glimpse into Ruby’s Future
Modular garbage collection signals a shift from a one-size-fits-all runtime toward a configurable platform.
If the ecosystem embraces it, Ruby could eventually offer:
- Low-latency collectors for real-time systems
- Memory-efficient collectors for constrained environments
- Throughput-optimized collectors for large applications
- Specialized collectors for emerging platforms
In other words, Ruby’s memory management may become as flexible as its language semantics.
🧾 Source
Ruby core repository documentation:
Feature discussion:
💎 Final Thoughts
Modular GC may not affect everyday Ruby code today, but it represents a foundational step toward a more adaptable and performant runtime.
For developers interested in Ruby internals, performance engineering, or the long-term evolution of the language, this feature is worth watching closely.
