#Pixi.jsの二つのモード
Pixi.jsはWebGL、Canvasの二つのモードで動きます。
そのどちらが使われるか、によって、メモリ事情が異なってきます。
Canvasモードの場合、メモリマネジメントの結構な部分をブラウザが行ってくれますが、WebGLモードの場合は、ほとんどこちら(JavaScript)まかせです。
どちらのモードを使うかは、環境によって決定されていて、
- モバイルの場合ー>強制的にCanvasモード
- それ以外の場合ー>可能ならばWebGLモード
となっています。
現状のRPGツクールMVのエンジンには、メモリ管理にまつわる問題を二つ抱えています。
#メモリブロート(メモリをため込む)問題
- Canvasモード:影響度はブラウザ依存
- WebGLモード:深刻
ImageManagerには、一度読み込んだ画像は使いまわす、キャッシュの仕組みがあるのですが、それを空にするメソッドがどこからも呼ばれていない問題です。
##Canvasモード時の挙動
Chrome系ブラウザの場合、Canvasオブジェクトが作られても、まるまる画素を保持しいているわけではありません。ある程度の複雑さになるまで、どこに何を描画したのかという、ベクタ的に保存しています。
Canvasの内部表現がSVGになっている、と想像していただけるとわかりやすいと思います。よってChrome系ブラウザでは問題になりづらいです。
一方Edgeは、Canvasが作成されるとまるまる画素を確保します。作りたびにです。この場合は、メモリブロートは深刻な問題たりえます。
このように、 内部実装がブラウザによって異なるため、動作が読めません 。
##WebGLモード時の挙動
WebGLの場合、モバイル時には深刻な問題になりますが、モバイルではCanvasモードで強制起動するため、モバイル時でかつChrome系ブラウザを使ってる限り、問題は起こりにくいです。
PCで動かす際は、PCのメモリ、GPU性能に依存します。
PCの場合、GPUメモリに入りきらなかったテクスチャはメインメモリに退避します。また、メインメモリ自体も、足りなくなったらスワップ等駆使して可能な限り動作しようとします。よって、Pictureがうん百枚、といった環境ではない限り、問題になりにくいです。
また、GCが管理するメモリの中に、GPUが管理するメモリは入っていません。OpenGLの仕様上、利用可能メモリをとる手段がないので仕方ないのですが、GC管理メモリは余裕があるのに、GPU管理メモリがいっぱいいっぱい、という可能性もあるわけです。
本来ならばGPU側メモリは手動で開放すべきなのですが、それをするには、結構手をいれないと難しいのが現状です。
#メモリリーク問題
- Canvasモード:不明
- WebGLモード:致命的
有志の調査で明らかになったのですが、遠景(Parallax)を使用して、ウインドウ開閉やマップ移動を繰り返した場合、結構な確率でメモリ不足に陥ります。
これはTileSpriteの実装の問題です。ウインドウ開閉を行うと、内部で再生成が発生し、PIXI.Texture.fromCanvasというAPIが呼ばれます。
これが曲者になっていまして、このAPI、与えられたCanvasをキーにしてキャッシュを行います。そのうえ、キーとなるCanvasは、呼び出しもとによって、テクスチャが再生成されるごとに毎回作り直しているのです。
つまり、ウインドウ開閉を行うごとに、使われないゴミがたまっていく、メモリリークが発生します。
#メモリとの闘い
以上のように、GCがあっても、メモリに関する問題はけっこう起きます。
本当に、気を付けたいものです!!