Luaメモリ詳細診断

Blog:https://blog.jp.uwa4d.com/2019/11/15/luaメモリ詳細診断/

 

現在、Luaはすでに各開発チームがプロジェクトのHot Fix機能を実現するための一般的な実装方法だと思われますが、プロジェクトに機能追加、バッグ修正は非常に柔軟で便利です。しかし、プロジェクトで大量にLuaを使用することにより、プロジェクト実行時の重要なパーフォマンス問題の一つでもあります。特にメモリ関連の性能問題は、メモリの割当過ぎかメモリリークかどちらも開発中のプロジェクトで集中的に発生しているようです。

 

このため、UWA GOTでLuaのメモリ詳細診断機能をリリースしました。すでにUWA GOT Onlineサービスを購入済みのユーザー様は、実機でテストしたデータをUWAホームページ にアップロードし、すぐLuaのメモリテストレポートを確認することができます。

 

現在のバージョンはすでに主流のuLua、ToLua、SLua とxLuaをサポートしております。開発チームがLuaのNativeライブラリをカスタマイズし、リネームすれば、UWAEngine.SetOverrideLuaLibを使用してライブラリ名を指定することができます。

 

Luaメモリ診断は全体ヒップメモリ、ヒップメモリの詳細割当てとMonoオブジェクト参照の三つの部分に分かれております。以下をご参照ください。

 

1、全体ヒップメモリ

本テストレポートではLuaの全体メモリトレンド及びLuaのいくつ重要なオブジェクトCountを表示しております。Table,UserdataとFunction(通常threadのCountが少なく且つ安定的であるあるため、ここでは表示されません)。

上図の通り、プロジェクトが実行されたフレームごとのLuaメモリの使用状況をはっきり確認することができ、それぞれの数値が当初の予定値よりずれているかどうか、またはメモリリークのリスクがあるかどうか検討できます。

 

2、ヒープメモリ詳細割当

本レポートでは開発者がLuaヒープメモリの割当の多い関数を特定するのによく使用されます。開発者のLuaヒップメモリ使用の最適化のため、これらの関数の任意の1フレームの割り当てられたスタック情報を確認でき、Lua GCの発生率や発生時のメモリコストの低減につながります。

 

備考:Lua関数のネーミング方法はX@Y:Z,内Xが関数名,取得出来ない場合はXがデフォルトでunknownに変わります;Yは当該関数が定義したファイルの位置;Zは当該関数が定義された終了の行番号。特に注意して頂きたいのは、LuaのスクリプトをBytecodeで実行される場合は,数値はずっと0になるため、テスト時はできるだけ、Luaのソースコードでの実行を推奨いたします。

 

また、Monoメモリの逆順分析機能と同じように、Luaのメモリ情報でも同様に確認することができます。閲覧方法を切り替えるだけで、どのLuaのスクリプトのどの行のコードで、大量のメモリを使用しているか見つかることができます。そして、開発者が直接対応されたLuaスクリプトを開き、その行のコードを修正でき、性能改善がこのように簡単にできます。

 

3Monoオブジェクト参照

すべてのLuaプラグインでは,以下のような類似仕組みが存在しますが

C#レイヤーにCacheを保持し、LuaにアクセスされたC#レイヤーのオブジェクトを参照します。この仕組みは主にLuaが再度C#オブジェクトにアクセスする際に、当該オブジェクトはすでにGCに回収され、ロジックエラーにつながることを防ぐためです。そのため、Lua内にあるC#レイヤーのオブジェクト参照用にCacheを保持すると、それを解放されず、このような参照が多くなればなるほど、C#レイヤーのメモリリークに繋がります。

 

開発者がこのような状況を調査しやすくするため、Monoオブジェクト参照のレポートでは、上述のCache内のC#レイヤーのオブジェクトを整理し、Cacheで現れたオブジェクトのタイプや各タイプのオブジェクトの合計数量を統計しました。当該オブジェクトはUnityEngine.Objectに継承され、当該オブジェクトタイプでDestroyされたオブジェクト数量も統計されます。詳細下図参照:

 

上図のそれぞれのオブジェクトタイプをクリックすれば、合計数量の変化を確認できます。ある数量を持続的に上昇しているタイプに対して、二つのサンプリングポイントの違うオブジェクト参照を比較すれば、さらにLua内の合理的ではない参照を特定することができます。