【CoR】配列のお話【フリーズ問題】

投稿者:    mini 光楼(114) 投稿日:2021/02/28 19:45

まずはこれ↓を実行してみて欲しい。これでも良いよ。
scene 'start' do
  i = 0

  update do
    # 配列生成
    arry = [0]*500000

    i += 1
    debug_log "配列生成回数:#{i}"
  end
end

# シーンを開始する
start_scene "start"


長さ50万の配列を連続で生成するプログラムですが、数十回でフリーズすると思います。
特にエラーもなく、何の前触れもなく止まります。これは困りました……。










え?





こんなに配列作らないから自分は関係ないって!?










……そうですか。
では今度はこれ↓を実行して見てください。
scene 'start' do
  i = 0

  update do
    # 配列生成
    arry = [0]*500000

    i += 1
    debug_log "配列生成回数:#{i}"

    # 配列削除
    arry = [] # <= 追加箇所
  end
end

# シーンを開始する
start_scene "start"

配列を初期化する処理を入れてみました。
これもフリーズしてしまいます。
初期化したつもりでも、実は残ってるんでしょうね。

つまり、ループ内で配列を生成するといつかフリーズしてしまう!
……配列が長ければ長いほど、多ければ多いほど、フリーズまでの時間は早くなる( ノД`)シクシク…
この問題が急に現実味を帯びてきたでしょう?(笑)数万ループなんてCoRなら一瞬ですよ。


ちゃんと「削除」すればいいんじゃないの?ってことで、以下のプログラムを用意してみました。
scene 'start' do
  i = 0

  update do
    # 配列生成
    arry = [0]*500000

    i += 1
    debug_log "配列生成回数:#{i}"

    # 配列削除
    arry.each do |item| # <= 追加箇所↓
      arry.pop
    end # <= 追加箇所↑
  end
end

# シーンを開始する
start_scene "start"

配列の最後尾を抜き出し、配列からは削除するpopメソッドを配列の長さ分ループさせることにより、全要素を削除しています。
ちょっと時間掛かりますが、実行して見てください。










こ れ も フ リ ー ズ す る で し ょ ?





CoRのドキュメントに配列を削除する方法はこれ以上書かれていないので、「Ruby 配列 削除 すべて」でググってみました。
そしたら、clearメソッドというのが出てきました。これを使ってみましょう!
scene 'start' do
  i = 0

  update do
    # 配列生成
    arry = [0]*500000

    i += 1
    debug_log "配列生成回数:#{i}"

    # 配列削除
    arry.clear # <= 追加箇所
  end
end

# シーンを開始する
start_scene "start"

早速実行してみてください。
どうです?今度は止まらないでしょう?

CoRのドキュメントに書かれてない方法なので動作の保証は出来ませんが、フリーズを避けるためには現状こうするしかないと思います。
このゲームがフリーズしてしまう問題を抱えてるんですが、この方法で直るといいなぁ……。


フリーズの原因が他にもあるんじゃないかと思って、テキストスプライトを大量に生成してみました。
これは確か7万個超生成したあたりでフリーズしたんですが、destroyで消せば大丈夫そうでした。

なので、フリーズは生成した配列が全部残ってる事が原因かなと思ってます。

以上!

コメントする

コメントするには、ログインする必要があります。

コメント一覧

Cdv30200 aoi icon mini aoihikawa(投稿日:2021/03/02 16:22, 履歴)
おまけの話

外部関数で作られた配列も
関数を抜けただけでは削除されずに残るようです

↓フリーズする
def hairetsu()
  # 配列生成
  arry = [0]*500000
end

scene 'start' do
  i = 0
  
  update do
    # 配列生成
    hairetsu()
    
    i += 1
    debug_log "配列生成回数:#{i}"
  end
end

# シーンを開始する
start_scene "start"


↓フリーズしない(その1)
def hairetsu()
  # 配列生成
  arry = [0]*500000
  arry.clear #明示的に開放する
end

scene 'start' do
  i = 0
  
  update do
    # 配列生成
    hairetsu()
    
    i += 1
    debug_log "配列生成回数:#{i}"
  end
end

# シーンを開始する
start_scene "start"


↓フリーズしない(その2)
def hairetsu()
  # 配列生成
  arry = [0]*500000
  return arry #配列を戻り値にしたい
end

scene 'start' do
  i = 0
  
  update do
    # 配列生成
    arr = hairetsu()
    arr.clear #使用後に明示的に開放する
    
    i += 1
    debug_log "配列生成回数:#{i}"
  end
end

# シーンを開始する
start_scene "start"
    mini 光楼(114)(投稿日:2021/03/02 21:42, 履歴)
お、検証ありがとうございます!

自分で消す処理を書かないといけないみたいですね。
Cdv30200 aoi icon mini aoihikawa(投稿日:2021/02/28 23:25, 履歴)
安全に処理するために
必要なテクニックと知識ですね

情報、検証
ありがとうございます