2ntブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Androidアプリ開発 (ガベージコレクション戦争編)

こんばんわ。フィブです。


前回OpenGLの描画に切り替えて画面表示を行ったところ一応表示はできました。
が、問題発生。
3秒に1回ほどなぜか一瞬画面が固まる。

OpenGLの実装方法ミスったのかと思ったけどそんなこともなく。
まさかOpenGLでやっても重い?! そもそも処理が重すぎたの!?
と焦ったところ見つけた情報。

「GC(ガベージコレクション)が発生すると全スレッドが100ms~300ms停止します」

はい、原因はこいつでした。ガベージ。
ご存じのとおりJavaは不要になったメモリを勝手に解放してくれます。これがガベージコレクション。
メモリ領域を勝手に掃除してくれちゃうのです。そのせいで止まると・・・。

Logcatで確認。
確かにLog上でGCなんちゃらって書かれた後に画面が一時停止してる。
絶対これだ。なんて迷惑な・・・。

いろんな記事を漁っていると、ゲームのループ処理に入ったら極力GCが発生しないようにプログラムを組め!
必要なものはループの前に全部メモリ確保すること。
など、結構注意事項が広まっておりました。
あたしはGCなんて意識したことないよ・・・。

実行中のメモリの割り当て解放状態は、DDMSのAllocation Trackerという機能で見れるらしいので見てみる。
確認するとあるわあるわ・・・。すごく頻繁にやりまくってる。

ソース上で確認。AllocationTrackerを確認しつつ以下一つ一つを修正していきます。

①new を絶対にしない!
  ローカル変数でもnewしたらメモリ割りあて→解放が発生します。
 必要なものはクラスのメンバ変数に突っ込んで使いまわすように修正しました。

②foreach文を使わない
  foreachはイテレータを生成して処理をするらしいのでメモリ割り当て解放が発生するようです。
  あたしのソースはArrayListを全部foreachで処理してたので全部以下のように書き直しました。
  凄い時間かかった・・・。
 
元:for( UserObject obj : mObjectList)
     ↓
  現:for( int i=0; i< mObjectList.size(); i++)

③enumクラスを使わない。
  enumクラスもメモリ割り当て→解放が頻発するらしいのでやめました。
  enumクラスはすべて定数(public static final 型) に書き換え。

④描画時にcreateBufferしない。
  前回導入したOpenGLで描画するクラスのとこですが、
  描画前にAllocationBufferでFloat型のバッファを作成しておりました。
  これがかなりメモリ食ってました。
  いいのか悪いのかわかりませんが、これも描画用のオブジェクトにFloatBuffer変数をメンバ変数に定義し
  使いまわすように修正。

さて、デバッグ実行してAllocationTrackerとにらめっこ。
明らかにメモリ解放頻度が減ってます。目に見えて減ってます。
LogcatもGC発生頻度が激減し、画面も止まらなくなりました!


しかし調査、対応で2,3日かかった・・・。疲れた・・・。
まさかガベージコレクションと戦う日がこようとは思いませんでした。
これからは敵視していきましょうっ

コメント
コメントの投稿
管理者にだけ表示を許可する