RubyにLazySweepのパッチを作った

plan

  • SweepをLazySweepにして、最大停止時間を改善する
  • Heap内のオブジェクト数がある一定を超えてからLazySweepに切り替わる
    • 通常のプログラムのスループットを落としたくないので
    • 今は一応100万にしている
  • LazySweepフェイズではHeapの配列の数本を、オブジェクト数が一定になるように選んでSweepする
    • 配列一本ずつのオブジェクト数が異なるため、Sweepの時間がばらつかないように調整した
  • Heapの配列が1.8倍づつ増えるのがメモリ効率的にあんまりよくないので、LazySweepが始まってからは少し抑えるようにした。1.1倍くらい。

 
理想は
「オブジェクトを何百万も作ってプログラムをぶんまわす時の最大停止を改善する。」
です。
その場合当然スループット性能が低下してしまうのはいかしかたなし。
 

code for benchmark

many_obj_make_test.rb
4千万くらいオブジェクトを作ってぶんぶん動くプログラムのベンチマークを取る

benchmark

改善表

  NormalGC LazyGC difference
GC call 25 122 488%
GC all time 20.7107973098755 25.096631526947 121%
GC ave time 0.82843189239502 0.205710094483172 25%
GC min time 0.00109386444091797 0.00130701065063477 119%
GC max time 2.03675007820129 1.47522187232971 72%
       
mark call 25 29 116%
mark all time 12.8536868203664 15.5769688482396 121%
mark ave time 0.514147472814657 0.537136856835849 104%
mark min time 0.000580083928070962 0.00107801053673029 186%
mark max time 1.3276491042925 1.32264307874721 100%
       
sweep call 25 103 412%
sweep all time 7.855925333919 8.48065461323131 108%
sweep ave time 0.31423701335676 0.0823364525556438 26%
sweep min time 0.000473063439130783 0.00092699914239347 196%
sweep max time 0.726729059708305 0.378772096009925 52%
       
program time 52.198 60.535 116%

 
グラフ
停止時間比較
GCタイム/時系列

 
NormalGCのMark・Sweep比較
タイム/オブジェクト数

 
LazyGCのMark・Sweep比較
タイム/オブジェクト数

 

result

最大停止時間が28%ほど改善
スループット性能が20%程悪化しました。
スループット悪化であるが、これは関数呼び出しのコストがかかったのも原因の一つだが、
GCの際に走らせていたTimer,printf処理などのprofile系のコストがほぼだと思われる。
 

next

IncrementalGCを作りたい。
拡張ライブラリ周りでのライトバリアがどうかなぁ。
 

追記

Matzにっき(2008-03-06)
GCの話があがっていました。
今回のパッチはそれにじょうじて作ったわけでは無く、
去年からこつこつ考えてきたものです。
(失敗作をこのブログに多々乗っけてます。。。)
 

追記2

ちなみにmake testが通る程度のものですので、
ちゃんと動かない可能性があります。(finalizeとかfinalizeとか)
反応が大きければそこもきっちりやりたいですが、
あんまり性能が上がらないことが分かったので違う方法を考えようかと思っています。
なんでやらないかも。