---
title: "Incremental Garbage Collection in Ruby 2.2"
description: "Ruby 2.2 introduces RincGC, an incremental garbage collector intended to reduce the long pause times that Ruby 2.1’s generational collector could produce during major GC. The approach splits marking into fine-grained steps interleaved with Ruby execution, while lazy sweeping remains incremental; because CRuby lacks sufficient write barriers, unprotected objects are rescanned before white objects are reclaimed. The article explains the white, grey, and black object model, the write-barrier safety problem, and uses GC::Tracer events with a Rails benchmark simulating 30,000 requests to measure pauses. In the reported measurement, generational GC produced seven large pauses with a maximum of about 15 ms, while incremental GC reduced the maximum to around 2 ms, without reducing total GC time or improving throughput."
---

# Incremental Garbage Collection in Ruby 2.2

[Heroku](https://yomu.fyi/company/heroku) · Koichi Sasada · Feb 4, 2015

**Type:** Explainer

## Summary

Ruby 2.2 introduces RincGC, an incremental garbage collector intended to reduce the long pause times that Ruby 2.1’s generational collector could produce during major GC. The approach splits marking into fine-grained steps interleaved with Ruby execution, while lazy sweeping remains incremental; because CRuby lacks sufficient write barriers, unprotected objects are rescanned before white objects are reclaimed. The article explains the white, grey, and black object model, the write-barrier safety problem, and uses GC::Tracer events with a Rails benchmark simulating 30,000 requests to measure pauses. In the reported measurement, generational GC produced seven large pauses with a maximum of about 15 ms, while incremental GC reduced the maximum to around 2 ms, without reducing total GC time or improving throughput.

## Context

Ruby’s mark-and-sweep collector has throughput and pause-time costs. Ruby 2.1’s generational collector improved throughput through fast minor collections, but major collections could still pause the application for a long time, affecting interactive web applications.

## Approach / What changed

RincGC performs major-GC marking incrementally by interleaving small marking steps with Ruby execution. Since CRuby lacks sufficient write barriers, it rescans write-barrier-unprotected black objects before collecting white objects; lazy sweeping also proceeds step by step. GC::Tracer and a Rails benchmark measure the resulting pauses.

## Takeaways

- RincGC reduces individual GC pauses by splitting marking into fine-grained steps, but total GC time remains the same or may be slightly longer because of incremental-GC overhead.
- CRuby’s write-barrier-unprotected objects require a full rescan before sweeping so that live objects referenced through unmanaged relationships are not mistakenly reclaimed.
- In the reported 30,000-request benchmark, the maximum pause fell from about 15 ms with generational GC to around 2 ms with incremental GC; seven large pauses were observed with generational GC.

**Tags:** [Garbage Collection](https://yomu.fyi/topic/garbage-collection), [Performance](https://yomu.fyi/topic/performance), [Ruby](https://yomu.fyi/topic/ruby)

- Source: [Heroku](https://www.heroku.com/blog/incremental-gc)
- Source URL: https://www.heroku.com/blog/incremental-gc
- Ingested by Yomu: 2026-09-09T14:23:51.283Z

[Read original post](https://www.heroku.com/blog/incremental-gc)
