From: "H.Yamamoto" Date: 2006-02-09T11:18:01+09:00 Subject: [ruby-dev:28325] Re: SEGV with zlib 山本です。 >GzipWriter がつながっている時には、根元から実際の IO に向かっ >て順番に finalize していく必要があります。 > >そうではない順に finalize してしまうと、finalize で書き込も >うとした時には書き込み先がすでに finalize 済み (close 済み) >で書き込めないことになります。 > >なので、オブジェクトが生きているというだけでは十分ではありま >せん。もちろんオブジェクトが生きているということ自体は重要で >すが、順序を制御する仕掛けも必要になります。 > >やるとしたら IO や GzipWriter に参照元を登録する機能をつけて、 >finalize 時にはまず参照元を finalize するのだろうか、と思っ >ています。 > >なお、Java でも finalizer の呼び出しの順番は不定なので、順序 >を制御する場合には自前でやらないといけないと思いますが、どう >してんのかな。 http://www.nminoru.jp/~nminoru/programming/boehm-gc3.html に Boehm GC がどうしているのかが載っていました。なるほど、 gc_mark と gc_sweep の間で、「マークされていない T_DATA で、 mark 関数と free 関数の両方が定義されているもの」に対して gc_mark_children を呼べば(自分自身はマークしない)ルートに 当たる T_DATA だけマークが外れた状態になるので、順序付けでき るんですね。(自分はマークしないというのは盲点でした) ただ、この方法にも問題があるらしく、それも記述されています。 ナイーブにこれを実装すると、T_DATA が全くないにも関わらず、 2割ほど遅くなるという結果が出ました(消してしまったので パッチがないのですが) GC.disable t = 0 1000.times do 100.times { ["1"] * 100 } t1 = Time.now GC.enable GC.start GC.disable t2 = Time.now t += (t2 - t1) end puts t ただ思うのですが、ruby GC にはまだ改善の余地があるんじゃないでしょうか。 上の結果から、heapslot を単に走査してフラグを調べるだけでも遅くなって いることがわかるので(要素が10000以上ある)明らかにフリーセルとわかっている 範囲は調べないようにするとか、ビットマップを用いてフリーセルを管理するとか、 T_DATA だけ別のスロットで管理するとか。(ビット演算のほうが高くついてしまう 可能性もあるし、最後のは上の問題専用ですが)