トップ » 技術記事 » RHG 片手に Ruby 1.9 を読む集い(The RHG Strikes Back)に参加した(4) - 第4回 RHG の逆襲

RHG 片手に Ruby 1.9 を読む集い(The RHG Strikes Back)に参加した(4) - 第4回 RHG の逆襲

タグ: Ruby

どうも、あかさたです。5/11(日)に第4回 RHG の逆襲(Ruby 1.9 のソースコードを読む勉強会)が行われました。第3回に引き続き今回も参加したので、その勉強会の模様をレポートします。

概要

勉強会の趣旨などは、以前の記事(第1回第2回第3回)を読んでいただくとして、まずは当日の概要を紹介します。

第4回も前回までと同じく新橋(汐留)のミラクル・リナックス株式会社さんの会議室で行われました。参加人数は約15名、スクール形式に座って発表者が発表しつつ、適宜参加者が自由にツッコミを入れていくというスタイルです。

以下、発表者のリストです。

  • 澤田さん(RHGの内容に沿って説明)
  • Yugui さん(コードの解説)
  • ささださん(Ruby における GC の戦略の紹介)

また、今回の勉強会の内容は、ニコニコ動画にアップロード(マイリスト RHG 片手に Ruby 1.9 を読む集い(The RHG Strikes Back))してあります。勉強会の雰囲気を知りたい方は、ぜひご覧ください。

第4回 RHGの逆襲

今回の内容は RHG でいうところの「第5章 ガ-ベージコレクション」に相当する部分です。メモリの確保と開放に関する部分を学習します。

Ruby の GC

ささださんによると、Ruby の GC 実装の戦略というか基本方針を列挙すると以下のようになるそうです。

  • Mark & Sweep(マーク&スイープ)
  • Stop the world
  • Conservative GC(保守的 GC)
  • write-barrier 不要
Ruby の GC のアルゴリズム

Ruby が採用している「マーク&スイープ」は、「全てのオブジェクトを走査して、必要なオブジェクト(参照されているオブジェクト)をマークして、マークのついていないオブジェクトを解放する」という方式です。対する戦略としては、リファレンスカウント、ストップ&コピーがあげられます。補助戦略としては Parallel GC、Generational GC(世代別 GC)があります。

リファレンスカウントは、オブジェクトへの参照数をカウントしておいて、カウンタが 0 になったら解放するというものです。ストップ&コピーは、マーク&スイープに似ていますが、オブジェクト領域を複数利用する方法です。ある領域にオブジェクトを生成して、GC の際に解放する必要のないオブジェクトはほかの領域に移動し、領域に残ったオブジェクトは解放します。欠点は、メモリを大きく必要とすることと、保守的 GC では作りにくいということです。保守的 GC については後述します。

Parallel GC は、並行に GC を実行します。マルチコア CPU などで有効な手法です。世代別 GC は、寿命の短いオブジェクトと寿命の長いオブジェクトを分類して、寿命の長いオブジェクトをマーク&スイープなどの対象から外すことで、処理を軽くする考え方です。

GC にはさまざまな種類がありますが、いずれにせよ、Ruby はマーク&スイープのみを採用しています。

Ruby の GC の特性

Stop the world」とは、Ruby の処理を止めて、GC を実行するという意味です。対する戦略として、Incremental GC や Concurrent GC を挙げることができます。前者は GC の処理を段階化することでアプリケーションが一度に停止する時間を小さくする考え方で、後者は停止させないで平行に GC する考え方です。

保守的 GC」とは、「疑わしきは罰しない」方針を取る GC です。そもそも、メモリだけを見れば、その値がポインタなのか整数なのか判断することができません。保守的 GC の考え方では、回収すべきオブジェクトのアドレスと偶然同じ整数がある場合、そのオブジェクトに参照があると判断して回収しません。ちなみに、数値とポインタを分けて厳密に GC をする考え方を Exact GC と呼ぶようです。

つまり、Ruby の GC は GC の実行時にアプリケーションの処理が一定時間停止する可能性があり、わずかにメモリが回収されない(メモリーリーク)可能性があるということになります。その代わり、開発しやすさを重要視していることになります。

write-barrier とは?

write-barrier とは、オブジェクトへの書き込み時にフックして GC 用に特別な処理を行う機構です。たとえば世代別 GC を実装するとします。

世代別 GC の問題点として、寿命の長いオブジェクトが寿命の短いオブジェクトを参照しているときに、寿命の長いオブジェクトはマークの対象とならないため、GC が寿命の短いオブジェクトをマークすることができず解放対象とみなしてしまうことが挙げられます。そこで、寿命の長いオブジェクトに寿命の短いオブジェクトへの参照を追加する際に、GC に対して寿命の短いオブジェクトをマークするように教えてやる処理を書く必要があり、そのような機構を write-barrier と呼びます。

ささださんによると、この write-barrier の負荷が世代別 GC の良さを殺してしまうことがあるとのことです。Ruby で世代別 GC を実装した例はあるものの(RHG でも紹介されています)、本家に取り込まれていない理由は、その辺にあるようです。

Series Navigation«第5回 RHG の逆襲

1 2

執筆者紹介

あかさた

あかさた

未踏(2006年度下期)でWeb上で動作するモデリング環境 Kodougu の開発をしてました。こちらでもブログを書いています。

TrackBack URL :