From: ruby-philia@... Date: 2007-03-27T23:01:18+09:00 Subject: [ruby-list:43318] 質問:参照されなくなったデータの行方(ちゃんとGCされたか)を知る方法は? こんにちは Ruby/GTKでいろいろ作ろうとしていましたが、HDDの物理的で損傷でデータが消えてやる気が無くなって しまっていたruby-philiaと申します。 今回るびまのRuby/SDLの記事を見てやる気を取り戻し、シューティングゲームを作ろうとしています。 そこでふと気になったことがいくつかあります。 1.参照されなくなったデータのGCのタイミングは? 2.そのタイミングを知る方法は?(プログラムに細工する方法とかありましたら) 3.GCするタイミングはわからないけど気にしなくていいはず?なのか。 4.こういったメモリ使用量の増減を知る仕掛けは作れるのか? 詳しく説明すると以下のようになります。 (長くなりますので興味の無い方は見ない方が良いです) chars = [] chars << Character.new loop do chars.each do |char| char.move char.draw end end とまぁ、こんな感じでキャラを動かして描画してを繰り返していました。 (実際のプログラムはhttp://blog.goo.ne.jp/ruby-philiaからダウンロードできます) すると、ときどきちらついたり、動いてないキャラがあるのを見つけました。 原因は、char.moveの中で chars.delete(self) if @y < 0 というように自分自身が画面外に消えたらchars配列から自分自身を削除するという方法を使っていたた めでした。うまく説明できないので、簡単な例として以下のようなことが発生していたのでした。 例1 ary = [1, 2, 3, 4] ary.each do |item| p [item,ary] end 実行結果 [1, [1, 2, 3, 4]] [2, [1, 2, 3, 4]] [3, [1, 2, 3, 4]] [4, [1, 2, 3, 4]] 予想通りの処理 例2 ary = [1, 2, 3, 4] ary.each do |item| ary.delete(2) if item == 3 p [item,ary] end 実行結果 [1, [1, 2, 3, 4]] [2, [1, 2, 3, 4]] [3, [1, 3, 4]] あれ?4が処理されなかった。 例3 ary = [1, 2, 3, 4] ary.each do |item| ary.delete(item) if item == 2 p [item,ary] end 実行結果 [1, [1, 2, 3, 4]] [2, [1, 3, 4]] [4, [1, 3, 4]] あれ?3が処理されなかった。 つまり、処理されなかった3や4が描画されなかったり、移動しなかったりで、ちらつきやコマ落ち?の ようになっていたことを突き止めました。 自分なりに例2や例3を回避する方法を考えたところ(2日間も考えてしまいました)、以下のようになり ました。 例2改 ary = [1, 2, 3, 4] ary.dup.each do |item| ary.delete(item) if item == 2 p [item,ary] end 実行結果 [1, [1, 2, 3, 4]] [2, [1, 3, 4]] [3, [1, 3, 4]] [4, [1, 3, 4]] 処理のシンプルさやすっきりしたコードを維持しつつ、処理し忘れもなくなりました。 元のコードに戻りますと以下のようになるわけですが、 loop do chars.dup.each do |char| char.move char.draw end end dupで利用した配列のコピーが、ちゃんとGCされているのかが気になって来ました。 実行速度が特に遅くなったりはしていないようなので問題ないかなと思っていますが、 実はメモリ領域をかなり食い続けてるのではないか?という心配も出てきました。 せいぜいサイズが200とか500程度の配列なので大した量にはならないのかな?と思いつつ 毎秒30回の描画を行うので3分もすれば30*180という量になります。 もし、実行終了まで増え続けているのであれば…と考えると怖くて夜も眠れません。 gc = GC処理するやつ def GC処理するやつ call gc puts "いまGCされましたよ" end みたいなことができるのでしょうか? それと、ソースを見た方や実際動かしてプレイした方で、もしアドバイスなどありましたら、いろいろ と教えてください。よろしくお願いします。