端的に言えばGCの話です
現在android向けのアプリをUE5で作っているのですが、デバッグ中にUIを付けたり消したりを繰り返すとどんどんfpsが低下する現象を発見しました。
デバッグコマンドで見てみるとメモリーがかつかつになっていたため調査をした話です。
主にこの問題が起きるのはメモリの少ないモバイルです。
remove系の処理は内部的には破棄されてないぞ!!!
まんまです。remove from parent関数やremove all widgets関数で非表示にすると思いますがこれ、nullptrを代入をしないと永遠にメモリ空間陣取ります!!!
destroy actorとかと同じ感じだと思っていたのがすべての間違いでした。
実際にやってみよう!
今回はwindowsデスクトップでの検証です。ue4.27です。
1ボタンを押すとcreat widgetとremove from parentを各50万回実行します
widgetはhello world!と書いてあるテキストとキャンバスパネルだけです。
実行してみる
対策してみよう!
get all widgets of call関数でtop level onlyのフラグを外すとremoveされたwidgetも取れます。
これをfor each loopで変数に上書きし続け、最後はnoneをセットすることでnull ptrを代入できます!
そしてdelayに0秒を入力すると1フレーム後に処理が走ります。(ue5ならdelay next見たいのがあるはずです)
その後collect gabagel関数を呼ぶことでシステム側で破棄してくれます~
結果
約1300MBまで減りました!最初の時よりかはメモリー食ってますが基本的にシステム側で破棄してくれた事が分かります !
まとめ
今回は参照が無く要素もほぼないwidgetでしたから大してメモリーは食っていませんでしたが、複数参照したり特にwidget switcherを使用したりしている場合、そのwidgetの各要素の変数が全てメモリ上に残ったままになるためモバイルではヒッチやfps低下の原因になります。nullptr入れましょう。