Reworking Ruby's Memory: Shopify and ANU Tackle Garbage Collection Challenges with MMTk

For decades, Ruby's garbage collector operated on relatively simple principles—until the demands of modern applications exposed its limitations. Now, a radical collaboration between Shopify and the Australian National University (ANU) is rewriting Ruby's memory management playbook by integrating the Memory Management Toolkit (MMTk), promising unprecedented performance gains through advanced garbage collection algorithms. But as the teams discovered, marrying Ruby's object model with cutting-edge memory management required solving intricate technical puzzles.

The MMTk Revolution: Beyond Mark-and-Sweep

MMTk isn't just another garbage collector—it's a GC construction toolkit that offers a modular, VM-neutral framework for building high-performance collectors. Unlike Ruby's traditional mark-and-sweep approach, MMTk provides access to sophisticated algorithms like:
- Generational Immix: Optimized for short-lived objects
- Sticky Immix: Specialized for high-throughput scenarios
- NoGC: For extremely low-latency environments

"Once a language plugs into MMTk, it can leverage a wide range of built-in garbage collection algorithms, many of which are considerably more sophisticated than Ruby's current implementation," explain the researchers. This flexibility could deliver substantial performance improvements for memory-intensive Ruby applications.

Currently, two implementations coexist: an advanced experimental fork maintained by the MMTk core team, and an upstream effort via Ruby's modular GC framework. While the latter lags in features, both aim to modernize Ruby's memory management.

Breaking Through Technical Barriers

The Object Pinning Dilemma

Ruby's introduction of object movement in version 2.7 created a fundamental conflict with MMTk's design. Many MMTk algorithms combine marking and moving phases, but Ruby's pinning mechanism—where certain objects can't be relocated—required inefficient double heap scanning.

The breakthrough came with Potentially Pinning Parents (PPP). By identifying objects that might contain unmovable references during allocation, MMTk maintains a compact PPP list:

# Simplified PPP concept
if object.contains_unmovable_references?
  mmtk.register_ppp(object)
end

During GC cycles, MMTk swiftly inspects only these PPP objects to pin necessary children before proceeding with parallel marking and moving. Crucially, years of Ruby core development have minimized PPP objects—today, primarily internal types and native gems.

Conquering the Parallel Finalization Bottleneck

MMTk's parallel garbage collector processes work packets across multiple cores, but a hidden adversary emerged: memory deallocation. When freeing malloc-allocated buffers (common in pre-Ruby 3.2 code), performance degraded with more threads:

Article illustration 1

Figure: Freeing 100 million 32-byte chunks across threads shows severe scaling limitations in common allocators (glibc, jemalloc, tcmalloc). Only mimalloc showed gains, plateauing at 4 threads.

The team's ingenious solution? Replace malloc with managed Ruby objects for core types (Array, String, MatchData). By making buffers GC-managed objects:
1. Finalization overhead disappears
2. Bump-pointer allocation replaces slower freelists
3. Automatic memory management eliminates manual free calls

"These buffers now have automatic memory management... they don’t need to do anything during finalization," the team notes. This approach leverages MMTk's ability to skip finalization entirely for non-malloc resources.

The Path Forward

The collaboration continues to refine techniques for object movement, JIT-GC integration, and optimized memory layouts. Lessons from MMTk are already influencing upstream Ruby development—proving that rethinking foundational systems can yield transformative performance gains. For garbage collection researchers and language implementers, this work demonstrates how academic rigor and production expertise can coalesce to solve real-world constraints.

As Ruby evolves beyond its scripting-language origins, sophisticated memory management becomes increasingly critical. The Shopify-ANU partnership isn't just optimizing garbage collection—it's helping redefine what's possible in dynamic language performance.

Adapted from Reworking Memory Management in CRuby by Shopify & ANU. Research presented at ISMM 2025.