Project

General

Profile

Feature #8024

Lazy sweep を on/off するための機能

Added by mrkn (Kenta Murata) over 4 years ago. Updated over 4 years ago.

Status:
Closed
Priority:
Normal
Target version:
-
[ruby-dev:47135]

Description

Lazy sweep を on/off する機能を追加するパッチを作りました。
このパッチは環境変数1つと GC のモジュール関数2つを追加します。

環境変数は RUBY_GC_DISABLE_LAZY_SWEEP です。
これに 0 以外の整数を設定して ruby を実行すると、
lazy sweep が off の状態で実行されます。

GC に追加されるモジュール関数は disable_lazy_sweep と enable_lazy_sweep です。
文字通り、lazy_sweep の on/off を切り替えるために使います。

このパッチを作るに至った経緯は、Lazy sweep が on の時だけ再現する SEGV が
弊社のテストコードで発生していたからです。
SEGV の発生条件がまだ絞れていないため、残念ながらバグ報告はまだできません。

運用上 Lazy sweep を止めておく必要があっために作ったパッチですが、
他の人の役にも立つかもしれませんので、こちらで提案させて頂きます。

trunk/2.0.0 用 → https://gist.github.com/mrkn/5096076

1.9.3 用 → https://gist.github.com/mrkn/5096071

Associated revisions

Revision 39901
Added by nari over 4 years ago

  • gc.c (GC_ENABLE_LAZY_SWEEP): new macro to switch lazy sweeping for debugging. [Feature #8024]

Revision 39901
Added by nari over 4 years ago

  • gc.c (GC_ENABLE_LAZY_SWEEP): new macro to switch lazy sweeping for debugging. [Feature #8024]

Revision 39901
Added by nari over 4 years ago

  • gc.c (GC_ENABLE_LAZY_SWEEP): new macro to switch lazy sweeping for debugging. [Feature #8024]

Revision 39901
Added by nari over 4 years ago

  • gc.c (GC_ENABLE_LAZY_SWEEP): new macro to switch lazy sweeping for debugging. [Feature #8024]

History

#1 [ruby-dev:47136] Updated by kosaki (Motohiro KOSAKI) over 4 years ago

えーと、一般論としてチューニングパラメータはdisable_hogehoge とかいう否定形は好ましくないよ。間違えるから。
環境変数は RUBY_GC_ENABLE_LAZY_SWEEP のほうがよいんじゃないかな。
GC.disable_lazy_sweepも有り難みがよくわかりませんでした。

#2 [ruby-dev:47137] Updated by mrkn (Kenta Murata) over 4 years ago

GC.disable_lazy_sweepも有り難みがよくわかりませんでした。

rspec が spec ファイル群をロードするだけで10分以上かかる場合があるので、
プロセスの起動時〜specファイルロード完了までは lazy sweep は有効であって欲しくて、
begin(:suite) で GC.disable_lazy_sweep することにしています。

ですから、私の個人的なユースケースでは GC.enable_lazy_sweep は使っていません。
GC.disable / GC.enable のペアとの対称性を保つために追加してあるだけだったりします。

環境変数は起動直後からオフにしたいときに使うようにしています。

#3 [ruby-dev:47139] Updated by kosaki (Motohiro KOSAKI) over 4 years ago

今後なにかあるたびに、GCにメソッドが2つづつ増えるのは非生産的なので、対称性だけが目的なら GC.enableにbool引数追加して、GC.enable_lazy_sweepもそうするってのが私の好みかなあ。すでにstressはboolean値のようだし。
ただの好みなのでむらけんさんの好みに合わないならこれ以上はプッシュしません

では。

#4 [ruby-dev:47140] Updated by sorah (Sorah Fukumori) over 4 years ago

bool 値化同意します。

#5 [ruby-dev:47145] Updated by mrkn (Kenta Murata) over 4 years ago

むらけんさんの好みに合わないなら

この件に関しては好みを主張できるほど詳しくないので、メソッド名から要/不要まで nari3 にすべての決めて頂こうと考えてました。
私は真偽値を与えて on/off を制御する方式でも問題ないと思ってます〜

#6 [ruby-dev:47146] Updated by authorNari (Narihiro Nakamura) over 4 years ago

このメソッドや環境変数を追加する動機が「SEGVが発生するかしないかの切り分けのため」なので、その用途だけでメソッド追加などをするのはやり過ぎかな、と思いました。
SEGVが直ったら用済みになっちゃうかもしれないですよね…。

それ以外の用途がなにかあれば教えてもらえると助かります。

#7 [ruby-dev:47147] Updated by mrkn (Kenta Murata) over 4 years ago

SEGVが発生するかしないかの切り分けのため

これは正確な表現ではなく、本当の動機は「SEGVを回避するため」です。

SEGVが直ったら用済みになっちゃうかもしれないですよね…。

そうですね。

それ以外の用途

ありません〜

#8 [ruby-dev:47179] Updated by authorNari (Narihiro Nakamura) over 4 years ago

  • Status changed from Assigned to Rejected

特にみなさんから反論もなさそうなのでRejectしておきます。

#9 [ruby-dev:47190] Updated by authorNari (Narihiro Nakamura) over 4 years ago

ちなみに以下のようにパッチを修正しないとヒープがうまく拡張してくれず、GCが多発するようです > mrknさん
https://gist.github.com/authorNari/5227985/revisions

#10 [ruby-dev:47191] Updated by naruse (Yui NARUSE) over 4 years ago

authorNari (Narihiro Nakamura) wrote:

ちなみに以下のようにパッチを修正しないとヒープがうまく拡張してくれず、GCが多発するようです > mrknさん
https://gist.github.com/authorNari/5227985/revisions

わたしも先日 lazy sweep 切ってデバッグしたくなったので、マクロ定義を見るとかでもいいので、
正しい lazy sweep を切るコード自体は入れておいて頂けませんか。

参考 https://github.com/nurse/rubyspec/commit/c02c78b3899fcf769084a88777c63de0fcebb48d

#11 [ruby-dev:47192] Updated by authorNari (Narihiro Nakamura) over 4 years ago

  • Status changed from Rejected to Open

なるほどです。デバッグ用途にマクロでONになるやつを作ってみます。

#12 [ruby-dev:47193] Updated by ko1 (Koichi Sasada) over 4 years ago

すみません、ちょっとわかってないんですが、
ObjectSpace.each_object 中って lazy GC 起きないようになってますよね。

(1) lazy sweep を止めるときは、別スレッドで適当に
ObjectSpace.each_object を実行しておく
(で、その中で sleep させておく)、というので行けると思ったんですが、
あってますか?

(2) で、ヒープの拡張がうまくいかない問題は、ObjectSpace.each_object 中に
も同様に発生するでしょうか? もしそうなら、それはそれで修正しないといけ
ないような気がします。

--
// SASADA Koichi at atdot dot net

#13 [ruby-dev:47194] Updated by authorNari (Narihiro Nakamura) over 4 years ago

ko1 (Koichi Sasada) wrote:

すみません、ちょっとわかってないんですが、
ObjectSpace.each_object 中って lazy GC 起きないようになってますよね。

(1) lazy sweep を止めるときは、別スレッドで適当に
ObjectSpace.each_object を実行しておく
(で、その中で sleep させておく)、というので行けると思ったんですが、
あってますか?

すみませんが、修正内容がよく理解できませんでした。
別スレッドで実行すると何が解決するのでしょうか?

(2) で、ヒープの拡張がうまくいかない問題は、ObjectSpace.each_object 中に
も同様に発生するでしょうか? もしそうなら、それはそれで修正しないといけ
ないような気がします。

はい、修正が必要だと思います(のでなおしておきます)。
ただ、ObjectSpace.each_objectの中でヒープが拡張していくようなコードは無限ループになる可能性があるので、そもそもあまり推奨されるコードじゃないですね…。

#14 Updated by authorNari (Narihiro Nakamura) over 4 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r39901.
Kenta, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


  • gc.c (GC_ENABLE_LAZY_SWEEP): new macro to switch lazy sweeping for debugging. [Feature #8024]

#15 [ruby-dev:47197] Updated by ko1 (Koichi Sasada) over 4 years ago

(2013/03/24 12:35), authorNari (Narihiro Nakamura) wrote:

すみません、ちょっとわかってないんですが、
ObjectSpace.each_object 中って lazy GC 起きないようになってますよね。

(1) lazy sweep を止めるときは、別スレッドで適当に
ObjectSpace.each_object を実行しておく
(で、その中で sleep させておく)、というので行けると思ったんですが、
あってますか?

すみませんが、修正内容がよく理解できませんでした。
別スレッドで実行すると何が解決するのでしょうか?

修正内容云々、という話ではなく、

(1-1) lazy sweep を切るには、ObjectSpace.each_object
を実行中は lazy sweep は無効になる

(1-2) 例えば、
Thread.new{ObjectSpace.each_object{sleep} # sleep で止まる
... 他の処理 ...
 とすると、「他の処理」実行中は lazy sweep 止まっている

(1-3) 新しいメソッドなどを定義しなくても、Lazy sweep を無効にする
ことができる

という話を確認したかったのです。もしかしたら、私が何かしら勘違いしている
かもしれないので。つまり、この ticket は簡単に実現できるんじゃないの、
と。もちろん、実装依存の bad know-how ですが、そもそも今回の用途は実装依
存の挙動に対する調査なので、まぁいいかなと。

(2) で、ヒープの拡張がうまくいかない問題は、ObjectSpace.each_object 中に
も同様に発生するでしょうか? もしそうなら、それはそれで修正しないといけ
ないような気がします。

はい、修正が必要だと思います(のでなおしておきます)。
ただ、ObjectSpace.each_objectの中でヒープが拡張していくようなコードは無限ループになる可能性があるので、そもそもあまり推奨されるコードじゃないですね…。

each_object の実行が止まらない可能性、ですよね。それは同意できますが、そ
の辺を回避するのは無理なんじゃないかなぁ。

で、この修正を入れないと、現状では (1) の「簡単に止められるんじゃない
の」というのは、「実はこういう制約が入る」、ということですかね。

--
// SASADA Koichi at atdot dot net

#16 [ruby-dev:47199] Updated by authorNari (Narihiro Nakamura) over 4 years ago

ko1 (Koichi Sasada) wrote:

(2013/03/24 12:35), authorNari (Narihiro Nakamura) wrote:

すみません、ちょっとわかってないんですが、
ObjectSpace.each_object 中って lazy GC 起きないようになってますよね。

(1) lazy sweep を止めるときは、別スレッドで適当に
ObjectSpace.each_object を実行しておく
(で、その中で sleep させておく)、というので行けると思ったんですが、
あってますか?

すみませんが、修正内容がよく理解できませんでした。
別スレッドで実行すると何が解決するのでしょうか?

修正内容云々、という話ではなく、

(1-1) lazy sweep を切るには、ObjectSpace.each_object
を実行中は lazy sweep は無効になる

(1-2) 例えば、
Thread.new{ObjectSpace.each_object{sleep} # sleep で止まる
... 他の処理 ...
 とすると、「他の処理」実行中は lazy sweep 止まっている

(1-3) 新しいメソッドなどを定義しなくても、Lazy sweep を無効にする
ことができる

という話を確認したかったのです。もしかしたら、私が何かしら勘違いしている
かもしれないので。つまり、この ticket は簡単に実現できるんじゃないの、
と。もちろん、実装依存の bad know-how ですが、そもそも今回の用途は実装依
存の挙動に対する調査なので、まぁいいかなと。

おおお、なるほど。おっしゃる通りだとおもいます。

(2) で、ヒープの拡張がうまくいかない問題は、ObjectSpace.each_object 中に
も同様に発生するでしょうか? もしそうなら、それはそれで修正しないといけ
ないような気がします。

はい、修正が必要だと思います(のでなおしておきます)。
ただ、ObjectSpace.each_objectの中でヒープが拡張していくようなコードは無限ループになる可能性があるので、そもそもあまり推奨されるコードじゃないですね…。

each_object の実行が止まらない可能性、ですよね。それは同意できますが、そ
の辺を回避するのは無理なんじゃないかなぁ。

で、この修正を入れないと、現状では (1) の「簡単に止められるんじゃない
の」というのは、「実はこういう制約が入る」、ということですかね。

(1)の方法で簡単に止められるけど、ヒープ拡張がうまくいかない制約が入る、という意味でしょうか?
だとしたらおっしゃるとおりだと思います(もうtrunkでは修正しちゃいましたけど :P)

Also available in: Atom PDF