Unity mmorpg手遊びluaメモリ最適化(一)

4242 ワード

本編では、マップなどのリソースがメモリを消費する場合については説明しません.
私たちのプロジェクトクライアントはtoluaホット・シナリオを使用しており、基本的にすべてのビジネスロジックはluaで実現され、戦闘関連のロジックもluaで実現されています.
この間、私たちのテストの同級生がWindowsでゲームテストをして各種の機能を検収した時、1時間ぐらい運んで、オペレーティングシステムの性能表示でUnityというプロセスが15個近くGを占めていることを示しました.プロセスをkillしてからUnityを再起動してから実行しなければなりません!
これは明らかにメモリの漏れの問題が存在して、結局私達は手遊びをして、メモリの占有量はpcゲームのあのようなレベルに達しないで、それから私は時間をかけて検査に着手します!
後で調べた結果、本当の意味での漏れではなく、gcが深刻すぎるため、メモリの割り当てを要求する速度がgcより速く、後で非常に多くのメモリの破片が発生した.大きなメモリを申請しようとすると、現在保持されているメモリ(本来使用されていないメモリの総量がユーザーの要求よりはるかに大きい場合でも)が需要を満たすことができず、オペレーティングシステムに申請し続けるしかなく、Unityが占有する総メモリがますます大きくなります.
メモリの問題を調べる時、私が使ったツールは主にUnityのProfilerとgithubの上で他の人のluaメモリの漏洩ツール(luaメモリの漏洩を調べる1つ/luaメモリの分配が速すぎる1つ/luaメモリとCPUの時間の統計を調べる1つ)を参考にして、具体的なウェブサイトは貼らないで、探してすぐあります!
そして、この問題の原因は主に以下の点です.
1.C#でluaを駆動するいくつかの論理スクリプトの関数(例えばUpdate、OnRenderImageなど)は、モジュール名の接合関数名の形でtoluaによって呼び出されたが、元の実装者は文字列の接合がgcを生む問題を考慮せず、フレームごとにC#で多くの新しい文字列オブジェクトを生成しmono gcを招き、フレームあたり3~4 KBくらいです.
2.ポストプロセッシングの特殊効果のシナリオは多くのmono gcをもたらして、大体フレームごとに6 KBで、私達のMainCameraの上で4、5個のポストプロセッシングのスクリプトを掛けたためです
3.luaのいくつかのビジネスロジックの計算では、クライアントのリアルタイム時間が使用されています.これはC#側からuserdataで与えられていますが、現在toluaは文字列の形式で64ビット整数値をサポートしているため、使用するたびにtonumber(tostring(realTime))変換操作が行われ、呼び出しが頻繁になると(例えばUpdateで呼び出される)、多くのlua string(gcオブジェクトでもある)が発生します
4.luaの戦闘ロジックの大量のベクトル計算(例えば位置/方向/回転)、例を挙げる:
 1 local function _init()
 2     this.curPos = Vector3.New(0, 0, 0),
 3     this.moveDirN = Vector3.New(1, 0, 0)
 4 end
 5 
 6 --...
 7 
 8 local function _update()
10     local nextPos = this.curPos + this.moveDirN * 3
11     --...
12 end

このとき_updateでnextPosを計算すると、フレームごとに2つのVector 3 tableが多く発生します.なぜなら、toluaはluaにVector 3というクラスをカプセル化しているからです(主な役割は、頻繁にC#とやり取りすることを避けることです.つまり、メモリを少し多く使って、客観的なcpu実行時間を節約することです).数学演算子の再ロードの実現です.一度に+-*/演算を計算するとnew Vector 3が1つ増えるが、これも合理的で、本来実現する上ではそうであるべきで、さもなくばユーザーは疑問を生むことができる!
5.イベント(例えばシーンイベント/主役アップグレードイベントなど)の配布では、元の人はオープンソースのイベントライブラリを使用しており、lua協程を使用してイベントの配布を処理しています.異なるリスナーに1つのイベントを配布するたびに、個別の協程を作成して処理しますが、戦闘中には様々な違いがありますが、イベントは配布する必要があります.つまり、この量はまだ大きいですが、具体的なgc数値はフレームごとに1 KB程度ですが、私たちのプロジェクトの現在の状況では、イベントの配布という操作には非同期の需要はなく、すべてのリスナーが直接実行する必要があります.あるイベントの処理時間が許容できない程度に達しているとは言っていません.だから、一時的に非同期という需要はありません.その後、コンシステントを追加し、複数の層をパッケージ化し、コンシステント多重化を行うと、新しいコンシステントは頻繁に発生しません.
6.他にも上記の4点と似ている点があり、呼び出し頻度が非常に頻繁な関数でlua tableが絶えず新しく作成され、この量は約8 KBである.
7.この点はまだ詳しく測定していませんが、推測は可能です.ネットメッセージの送受信です.モバイル、スキルなど、頻繁なメッセージもあります.毎回newです.後続もホットスポットかもしれません.
8.7と同様に、視野範囲内のすべてのエンティティの移動、技能を処理するこれらの論理も比較的多くのlua gcを招く可能性があり、後で確認してみる.
上記のいくつかの大きな原因を確認した後、相応の最適化案を使って最適化して、これは詳しく言わないで、原因がすべて確認したため、方案は基本的に確認したのです:構想は1つで、どのように避けてあるいは最大限gcを減らします!今の段阶で私达のゲームのpcの上のメモリの占用は基本的に比较的に安定して、2时间戦い続けて、多く分配したメモリの占用は基本的に数十Mのこのレベルで、后で更に携帯电话の上で更に确认するテストを行います!
最後に書きます:Unity Profilerを開く運転中、それ自体もmonoメモリを占有しているので、これは誤導されないように注意しなければなりません.例えば、Memory Profilerで自身が生成したgc曲線は、スイッチでCPU Profilerでの表示をオン/オフにすることができます.
 
2020-08-21
本編が終わり、転載は出典を明記してください——紅葉が赤くない