Version: 5.5
メモリ
アセットの監査

コルーチン

コルーチンは、他のスクリプトコードからは異なる形で実行されます。ほとんどのスクリプトコードは、パフォーマンス出力内で、特定の Unity コールバック呼び出しの下の一箇所にのみ表示されます。ただし、コルーチンの CPU コードは出力内で常に二箇所に表示されます。

あるコルーチンの初期コード(コルーチンメソッドの開始から初回イールドまで)の全ては、そのコルーチンの開始された場所に表示されます。通常はこれは、 StartCoroutine メソッドが呼び出された場所になります。 Unity コールバックから生成されるコルーチン([例] IEnumerator を戻す Start コールバック)は、最初にそれぞれの Unity コールバック内に表示されます。

コルーチンのその他のコード(初回再開時点から実行完了まで)は全て、 Unity のメインループ内に表示される DelayedCallManager ライン内に表示されます。

なぜ上記のようになるか理解するために、コルーチンの実行される仕組みを考えてみましょう。

コルーチンは、 C# コンパイラによって自動生成されるクラスのインスタンスに基づいています。このオブジェクトは、(プログラマーにとっては単一のメソッドである)複数の呼び出しにわたってコルーチンのステート(状態)をトラッキングするために必要とされます。コルーチン内のローカルスコープ変数は複数の yield コールにわたって維持されなければならないため、これらのローカルスコープ変数は生成されたクラス内に巻き上げされ、その結果、コルーチンの持続時間を通してヒープに割り当てられたままになります。また、このオブジェクトはコルーチンの内部ステートのトラッキングも行っており、コード内のどの時点で、イールド後にコルーチンが再開しなければならないかを記憶しています。

このため、コルーチンの開始によって掛かるメモリ負荷は、一定のオーバーヘッドコストに、そのローカルスコープ変数のサイズを足したものということになります。

コルーチンを開始させるコードがこのオブジェクトの構築と呼び出しを行い、その後このコルーチンのイールド条件が満たされた時点で、 Unity の DelayedCallManager がそれを再度呼び出します。コルーチンは通常別のコルーチンの外で開始されるので、その実行コストは上述の 2 箇所に分割されます。

上のスクリーンショット内では、 DelayedCallManager がいくつかの異なるコルーチンを再開している箇所がこれに当たります。主なものは PopulateCharactersAsyncLoadLoadDatabase です。

一連の処理がある場合、可能であれば、個々のコルーチンの数がなるべく少なくなるように凝縮することをお勧めします。入れ子になったコルーチンは、コードの明瞭化や維持の面では大変優れていますが、オブジェクトがコルーチンをトラッキングしているため、メモリオーバーヘッドが高くなってしまいます。

あるコルーチンがほぼ毎フレーム実行されていて、長期間の処理long-running operationsをイールドしていない場合は、一般的には、それを Update または LateUpdate コールバックに置き換えたほうがより読み易くなります。特にlong-running or infinitely-loopingコルーチンにおいてはこれが顕著ですparticularly true。

It is important to remember that coroutines are not threads. Synchronous operations running within a coroutine still execute on the main thread. If the goal is to reduce CPU time spent on the main thread, it is just as important to avoid blocking operations in coroutines as in any other script code.

コルーチンは、長時間の非同期処理を扱う場合に使用するのが最適です。例えば HTTP 通信やアセットの読み込み、ファイル出入力の完了の待機などです。

メモリ
アセットの監査