« メモリと OutOfMemoryError | メイン | 遅延確保と明示的解放 »

2012年04月05日

吉里吉里Java:: View 周りのメモリ使用量削減検討

    

View 周りでどれくらい変わるのか確認してみた。
Xperia arc 854x480 で確認したところ――
SurfaceView のみの場合、Java ヒープに約2.7MB、ネイティブヒープに約4.2MB と約7MB。
GLSurfaceView でそのまま設定した場合、Java ヒープに約2.7MB、ネイティブヒープに約4.8MB と約7.5MB。
GLSurfaceView で GLSurfaceView.setEGLConfigChooser( 8,8,8,0,0,0 ); と GLSurfaceView.Renderer を実装したクラスを GLSurfaceView に設定する前に指定して、ステンシルやデプスバッファを使わないようにすれば、SurfaceView より少し使用メモリが多い程度でほとんど同じサイズになった。
約0.5MBはデプスバッファだろうか。詳しくは調べていない。
GLSurfaceViewを使えば、バックバッファ等 VRAM に配置されて使用量が減るかとも思ったが、そんな事はなかった。
ImageView (640x480の画像を指定) のみの場合、Java ヒープに約2.7MB、ネイティブヒープに約5.4MB と約8.1MB

SurfaceView を使うのが一番使用メモリ量が少なそうだ。

これらのサイズは画面サイズが異なると当然使用量に変化が出ると考えられる。
実際、EeePad transformer TF101 (1280x800) では、SurfaceView のみの起動で 約9MB使われていた。

検索したところ Xperia Arc の VRAM はメインメモリと共有のようだ。
GLSurfaceView にして、テクスチャに転送しても使用メモリ量が減らなかったり、GLSurfaceView でも差がないのはこの辺りが原因だろうか? 詳しくは調べていないが、使用メモリ量が減らない機種があるのなら、GLSurfaceView に対応してもあまり意味はなさそうだ。
将来的に選択可能になっていても良いとは思うが。


吉里吉里Java では、オフスクリーンバッファを使用している。
SurfaceView は、ダブルバッファリングを使って描画しているので、フリップすると1フレーム前の画像が入っているため差分描画を行う吉里吉里Java(オリジナルと同じ)だとうまく描画出来ない。
Android 側のソースをざっと見たところ SurfaceHolder.lockCanvas( Rect dirty ) で、dirty を指定すると、フロントバッファから dirty 以外の領域をコピーして、Canvas の clipRect に dirty が指定された Canvas が返って来る。
Surface.unlockCanvas でロック解除するとフリップを行わずにロック解除されるようだから、差分描画の1回目に dirty rect を指定しフロントバッファから変更しない部分をコピーして、差分描画し2回目以降は、dirty rect に null 指定して全体を更新する指定してコピーしないようにすることでオフスクリーンバッファを使わないように出来なくはない。
( 実際にこのような挙動になるのかどうかは動作させて確認をしたわけではないので、もしかしたら違う挙動かも知れない )
ただ、吉里吉里Java でゲームのサイズと画面サイズが異なり、拡大縮小が必要となった時差分描画で誤差が出て隙間が出来てしまう可能性がある。
オフスクリーンバッファで画像を保持しておいた方が良い局面もあるので、結局オフスクリーンバッファを使用するのが無難な実装だと考えられる。

SurfaceView でオフスクリーンバッファを使うと言う、元々の実装がやはり良さそうと判断した。
最終描画周りで使用メモリ量を削減できないかいろいろと検討したが、この辺り削るのは難しそうだ。



投稿者 Takenori : 2012年04月05日 00:57




comments powered by Disqus
Total : Today : Yesterday : なかのひと