Why Ruby 2.1's generational garbage collector is a Big Deal™:
You might have seen these links today:
The current MRI garbage collector sucks. Everybody knows that, including
the Ruby core team. Why is it so difficult to improve? Because backwards
compatibility. After seeing what happened to Perl 6 and Python 3, Matz
has been very reluctant of making drastic changes to Ruby. C extensions
are especially important.
C extensions in MRI are quite powerful, and there's one specific feature
that causes problems. Direct access to arrays and structs:
RARRAY_PTR(arr) = new_value;
Most advanced garbage collectors require write barriers: A piece of code
that runs everytime a pointer changes value. With direct access to
arrays you lose write barriers.
For a long time we thought we only had two options:
(1) Introduce a completely new C extension API that handles write barriers.
(2) Forget about a generational garbage collector.
## The solution
So how does the generational garbage collector in MRI 2.1 work? It
separates all objects into two categories: *Sunny* objects and *shady*
objects. All objects starts as sunny objects. They are the well-behaved
objects. Suddenly a C extensions come and tries to access RARRAY_PTR(obj).
Yikes, we now have no control over what can happen to the object. It
Sunny objects are traced using the generational garbage collector. Shady
objects are always traced (as they were a young generation). This means
that the generational collector gracefully handles cases where some C
extension *might* have directly changed a value. C extensions which uses
RARRAY_PTR will continue to work, they just won't get the performance
improvements of the new generational collector.
## The deal
The actual generational garbage collector and its performance isn't
the important thing here. What really matters is this:
Ruby 2.1 has write barriers!!
| I changed OBJ_WB(a, b) interface to OBJ_WRITE(a, ptr, b).
| This interface do two things:
| (1) *ptr = b
| (2) make write barrier with a and b
| In some cases, we can't get ptr to store b, so I add another
| interface OBJ_WRITTEN(a, oldval, b). This only makes wb.
Write barriers opens up a lot of opportunities for implementing various
garbage collectors. The impossible has become possible.
| @judofyr Alternative title: "MRI's GC catches up with the rest of the world".
So so true.