ガベコレの本格導入へ向けて
abdev 9月 4th, 2006まずは調査から。一般的に、GCと言うとJavaや.NET言語で採用されている印象がありますね。確保されたメモリを自動的に解放してくれるというプログラマにとっては非常にありがたい機能、強いて言えば一度でもコレに慣れてしまうと、C言語のmalloc/freeには戻れないという話さえも耳にします(私の周りでもこの状態に当てはまる方が何名かいます)。
GCの実装は、言語が提供するか、ライブラリが提供するかに分別されます。JavaはVMが担当し、.NETはCLRが担当します(ガッチリと、言語が提供しています)。逆に、C/C++でGCを活用したい場合は、BoehmGCやboost::shared_ptrなど、外部ライブラリを取り込むことで実現できたりもします。これらの問題は手法ですので、将来的にABはこの方法でいきますということは、現時点では言及できません。
そして、GCにはいくつかの種類があるようです。それぞれのメリット・デメリットも様々。しかしながら、昨今のオブジェクト指向言語に一番適した手法が見いだされてきているようです。
- 参照カウンタ方式 … オブジェクトポインタのコピーと破棄を監視し、参照カウンタの増減を行う。カウンタが0になったら自動的にdeleteしてあげる。
- Mark & Sweep … メモリ使用量が増えるなどの一定条件が整った場合にGCを発動させる方式。スタティック領域とスタック領域(即ち、グローバル変数とローカル変数すべて)をスレッド毎にチェックし、使われていないオブジェクトポインタがあればdeleteしてあげる。
- 世代型GC … Mark & Sweep方式を新世代、旧世代の2つの世代にわけて効率的に管理する手法。Javaが世代型GCの採用を行っているのは有名な話。
ネイティブコンパイラとして実装しやすいのは、まずは参照カウンタでしょうか。しかし、参照カウンタ方式はGCの負荷が分散されるメリットの反面、循環参照への未対応や処理速度の鈍化が慢性的な問題として浮上してしまうという非常に大きなデメリットも存在しています。これらの問題から、最近の言語が積極的に参照カウンタ方式のGCモドキを採用するという傾向は薄いようです。
私の頭の中でも、明確な実装手法が整理されていないのですが、どうやらMark & Sweepの手法をベースにした、保守的GCの機構を言語ベースで提供するというのが一番良い方法なのかもしれません。欲を言えば、優秀な仮想マシンが提供するGC機能をコンパイラが提供する一機能として実現していきたいものです。
どちらにせよ、ABはNew 〜 Deleteでオブジェクトの確保・破棄を行うのを一般的な手法として提示しているので、それらを根本から覆すことは避けようと思います。将来的に、GCNew、GC_mallocなどの機構を取り入れられれば良いかな〜と思っています。
Wikipedia – ガベージコレクション:
チューニングのためのJavaVM講座(後編)〜ガベージコレクタの仕組みを理解する〜:
http://www.atmarkit.co.jp/fjava/rensai3/javavm02/javavm02_1.html
Recent Comments