tail -f judofyr

2013-09-16

cat 18:59:30 UTC
Ruby 2.1

Why Ruby 2.1's generational garbage collector is a Big Dealâ„¢:

You might have seen these links today:

* <http://www.infoq.com/news/2013/09/ruby-2-1-gc-revamp>
* <https://news.ycombinator.com/item?id=6392249>

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)[0] = 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
becomes shady.

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!!

Koichi:

| 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.

<http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/54705>

Write barriers opens up a lot of opportunities for implementing various
garbage collectors. The impossible has become possible.

cat 19:12:20 UTC

<http://twitter.com/YorickPeterse/status/379683788302725120>

| @judofyr Alternative title: "MRI's GC catches up with the rest of the world".

So so true.