Unity のコードには数多くのプロファイラーマーカーが用意されており、アプリケーションで何に時間がかかっているかを知ることができます。以下の表では、よく使われるマーカーの役割を説明します。
メインスレッドの基本マーカーは、アプリケーションに費やされた時間と、エディターやプロファイラーのアクティビティに費やされた時間を明確に区別します。また、ProfilerRecorder は、これらのマーカーを使って、メインスレッドのフレームのタイミングを計ることもできます。
マーカー | 機能 |
---|---|
PlayerLoop | アプリケーションのメインループから発生するすべてのサンプルを含みます。プレイヤーがエディターでアクティブな再生モードで実行されているときに、再生モードではなくエディターをターゲットにする場合、PlayerLoop は EditorLoop の下にネスト状にサンプリングします。 |
EditorLoop (エディター専用マーカー) |
エディターのメインループから発生したすべてのサンプルが含まれます。これは、エディターでプレイヤーをプロファイルする間のみ存在します。プロファイラーで再生モードをターゲットにすると、EditorLoop のサンプルは、プレイヤーを含むエディターのレンダリングと実行に費やされた時間を示します。 EditorLoop マーカーの下では、プロファイラーはそれ以上の詳細なデータを記録しません。これは、プロファイラーが再生モードをプロファイルしているときにエディターコードが出力するサンプルが、プロファイリングのオーバーヘッドを大きくするためです。 Unity は、EditorLoop マーカーからのサンプルを CPU Profiler モジュールチャート で Others に分類しています。その結果、EditorLoop のサンプルは、通常、そのカテゴリで最大の割合を占めます。もし、この時間のエディターのアクションや、Others カテゴリの詳細な内訳を見たい場合は、[代わりに Profiler のターゲットを Editor に変更してください。もし、Editor がこの時間に何をしているのか、また、 Others カテゴリに貢献している他のもののより詳細な内訳を見たい場合は、Profiler のターゲットを Editor に変更してください. Profiler のターゲットを Editor に切り替えると、CPU Profiler モジュールの詳細ペインでの Profiler の表示内容と、CPU Profiler モジュールのチャートでのカテゴリの内訳が変わります。これは、前は EditorLoop サンプルの下に隠されていたサンプルが、それぞれのカテゴリーに反映されるからです。 |
Profiler.CollectEditorStats (エディター専用マーカー) |
さまざまなアクティブなプロファイラーモジュールの統計の収集に関連するサンプルが含まれます。 特定のモジュールが負担するオーバーヘッドを取り除くには、そのモジュールのチャートを閉じるか、Profiler.SetAreaEnabled を呼び出してください。 ** 注意:** 内蔵カウンタを使用するカスタム Profiler モジュールは、それが属するモジュールが無効化されていても、内蔵カウンタの領域を有効にします。Profiler がこれらの統計を収集して収集のオーバーヘッドが発生するのを防ぐには、ビルトイン Profiler モジュールとカスタム Profiler モジュールの両方が無効になっていることを確認してください。 |
Unity Editor でプロファイルするときにのみ表示されるマーカーがあります。これらのマーカーは、プレイヤー関連のアクティビティでは表示されず、エディターアクティビティにのみ関連します。エディター専用のマーカーには、GetComponentNullErrorWrapper (null コンポーネントの使用を特定する)、CheckConsistency (オブジェクトの設定を検証する)、CheckAllowDestructionRecursive (破壊のチェック)、Prefab 関連のアクティビティなどが含まれます。
デフォルトでは、CPU Profiler モジュールの Hierarchy ウィンドウでは、エディター専用マーカーを持つサンプルスタックは折りたたまれ、EditorOnly [サンプル名]
という名前になります。これらのサンプルスタックやその子サンプルは、ガベージコレクションのトリガーとなるマネージ割り当ての原因となる可能性がありますが、折りたたまれている場合、その親サンプルの GC.Alloc 値には影響しません。
デフォルトの動作を変更するには、モジュールの詳細ペインの右上で、コンテキストメニューを選択し、Collapse EditorOnly Samples 設定を無効にします。これを行うと、サンプルを展開して、囲んでいるマーカーにその GC.Alloc 値を反映させることができます。
このオプションは、Timeline ビューには影響を与えず、サンプルとその子は展開され表示されます。これらのマーカーが付いたサンプルは、エディターのみのアクティビティに関連しており、マネージ割り当ての削減には影響しないため、通常は無視して構いません。しかし、再生モードでのパフォーマンスへの影響が問題になっている場合は、これらを調査するとよいでしょう。
ジョブシステム を使用している場合を除き、スクリプトコードのほとんどは以下のマーカーの下にネストになっています。ジョブシステムのサンプルについては、マルチスレッドマーカー のセクションを参照してください。
Unity の更新ループの詳細については、イベント関数の実行順序 のドキュメントを参照してください。PlayerLoop.SetPlayerLoop を使って、プレイヤーループ に独自のコールバックを挿入した場合、サブシステムとして入力した場合はスクリプトの更新サンプルはそれぞれのメイン PlayerLoopSystem マーカーの下に表示されます。メインループに直接入力した場合は、単独で表示されます。
マーカー | 機能 |
---|---|
BehaviourUpdate | MonoBehaviour.Update メソッドのすべてのサンプルが含まれます。 |
CoroutinesDelayedCalls | 最初の yield 後の Coroutines のすべてのサンプルが含まれます。 |
FixedBehaviourUpdate | Monobehaviour.FixedUpdate メソッドのすべてのサンプルが含まれます。 |
PreLateUpdate.ScriptRunBehaviourLateUpdate | Monobehaviour.LateUpdate メソッドのすべてのサンプルが含まれます。 |
Update.ScriptRunBehaviourUpdate | MonoBehaviour.Update とCoroutines のすべてのサンプルが含まれます。 |
これらのマーカーには、CPU が GPU のデータ処理に時間を費やす箇所、または、GPU の終了を待機しているかもしれない箇所のサンプルが含まれます。GPU Profiler モジュール が使用できない場合や、オーバーヘッドが大きすぎる場合は、プロファイラーモジュールの詳細ペインにこの情報は表示されません。これらのマーカーに含まれるサンプルは、アプリケーションが CPU 関連か GPU 関連かを判断するのに役立ちます。
マーカー | 機能 |
---|---|
WaitForTargetFPS |
Application.targetFrameRate が指定した目標の FPS のために、アプリケーションが待機した時間を示します。 サンプルが Gfx.WaitForPresentOnGfxThread のサブサンプルである場合、アプリケーションが GPU を待つのに費やした時間を表します。例えば、QualitySettings.vSyncCount で設定されている場合やターゲットプラットフォー ムで vSync が強制されている場合、GPU が次の VSync を待つために費やされた時間になります。ただし、GPU がフレームの計算を完了していない場合は、このマーカーが付いたサンプルも出力されます。 このマーカーを使用したサンプルが多くの時間を使用する原因を特定するには、CPU Profiler モジュールの Timeline ビュー に切り替えます。このビューでは、レンダースレッドで何が起こったか、現在のフレームで終了するこのサンプルと周囲のフレームで終了する同じサンプルの間に経過した時間を確認できます。 間隔がアプリケーションのフレーム時間が本来あるべき時間 (目標フレーム レートまたは vSync に基づく) よりも長い場合、フレームのレンダリングまたは計算に時間がかかりすぎてしまいます。その場合はレンダースレッドを調べて、コマンドを準備して GPU に発行するために行った他の作業に比較して Gfx.PresentFrame に費やした時間を確認してください。レンダースレッドが Gfx.PresentFrame により多くの時間を費やしている場合、レンダリング作業は GPU の性能限界によって制約される条件下にあります (GPU 依存)。レンダースレッドの時間がコマンドの準備に費やされた場合、アプリケーションは CPU の性能限界によって制約される条件下にあります (CPU 依存) アプリケーションが GPU 依存の場合に何に注目すればよいかを知るには、Unity Profiler またはプラットフォームのプロファイラーで GPU 作業をプロファイルします。詳細については、ユーザーマニュアルの グラフィックパフォーマンス を参照してください。 ノート: エディターは GPU 上で VSync を行わず、代わりに WaitForTargetFPS を使用して VSync の遅延をシミュレートします。プラットフォームによっては、特に Android や iOS では、VSync を強制したり、デフォルトのフレームレートの上限を 30 や 60 に設定しています。 |
Gfx.PresentFrame | GPU がフレームをレンダリングして表示するのをアプリケーションが待機する時間を示します。これには VSync を待機する時間も含まれます。 メインスレッドの WaitForTargetFPS マーカーは、VSync の待機に費やされる時間を示します。 |
Gfx.ProcessCommands | レンダースレッドのレンダリングコマンドのすべての処理が含まれます。この処理時間の一部は、メインスレッドからの VSync または新しいコマンドの待機に費やされる場合があります。それは、その子サンプル Gfx.WaitForPresentOnGfxThread から確認できます。 |
Gfx.WaitForCommands | 新しいコマンドに対し、レンダースレッドの準備ができていることを示します。このマーカーは、メインスレッドのボトルネックを示す場合もあります。 |
<GraphicsAPIName>.WaitForLastPresent 例:GfxDeviceD3D11.WaitForLastPresent GfxDeviceD3D12.WaitForLastPresent GfxDeviceMetal.WaitForLastPresent |
このマーカーが付いたサンプルは、メインスレッドが GPU がフレーム番号を画面に反転するのを待機したときに表示されます (Time.frameCount - QualitySettings.maxQueuedFrames + 1 )。つまり、QualitySettings.maxQueuedFrames が 1 より大きいと、この時間が、アプリケーションが前のメインスレッドフレームでレンダリングを要求したフレームを GPU が反転するのを待つために費やされることになります。このサンプルの詳細と Unity のフレームパイプラインの概要については、Unity の Delta Time の修正に関するブログ記事 を参照してください。 |
Gfx.WaitForPresentOnGfxThread | メインスレッドが次のフレームのレンダリングを開始する準備ができていたが、レンダースレッドが GPU がフレームを表示するのを待機し終えなかったことを示します。これは、アプリケーションが GPU 依存であることを示している可能性があります。 レンダースレッドが同時に何に時間を費やしているかを確認するには、CPU Profiler モジュールの Timeline ビュー を確認してください。 レンダースレッドが Camera.Render で時間を費やしている場合、アプリケーションが CPU 依存で、ドローコールやテクスチャを GPU に送信するのに時間をかけすぎている可能性があります。 レンダースレッドが Gfx.PresentFrame で時間を費やす場合、ゲームは GPU 依存か、GPU の VSync を待機している場合があります。Gfx.WaitForPresentOnGfxThread の WaitForTargetFPS サブサンプルは、アプリケーションが VSync の待機に費やす 現在 (Present) のフェーズの部分を示します。現在のフェーズは、Unity がグラフィックス API にバッファを交換するように指示してから、この操作が完了するまでの時間です。 |
Gfx.WaitForRenderThread | レンダースレッドがコマンドストリームにあるすべてのコマンドを処理するのをメインスレッドが待機していたことを示します。このマーカーのサンプルは、マルチスレッドレンダリングでのみ表示されます。 |
このサンプルは、Mono または IL2CPP のスクリプティングバックエンドアクティビティを強調しており、ガベージコレクションや割り当てに関する問題のトラブルシューティングに役立ちます。
マーカー | 機能 |
---|---|
GC.Alloc | マネージヒープの割り当てを示します。それには、自動ガベージコレクションの対象となるマネージアロケーション (割り当て) が含まれます。アプリケーションが自動ガベージコレクションに費やす時間を短縮するためには、これらのタイプのサンプルを最小限にする必要があります。 |
GC.Collect | ガベージコレクションに関連するサンプルを示します。Unity がガベージコレクションを行う必要があるときは常に、プログラムコードの実行を停止し、ガベージコレクターがすべての作業を終了したときにのみ、通常の実行を再開します。ノート: インクリメンタルガベージコレクション が有効な場合、ガベージコレクターが 1 フレームで作業を終えない場合があります。 この中断により、アプリケーションの実行に 1 ミリ秒未満から数百ミリ秒の遅延が発生する場合があります。これは、ガベージコレクターの処理に必要なメモリの量や、アプリケーションが実行されるプラットフォームによって異なります。詳細については、自動メモリ管理 のドキュメントを参照してください。 |
Mono.JIT Mono 専用 |
スクリプトメソッドの実行時 (JIT, just-in-time) コンパイルに関連するサンプルが含まれます。関数が初めて実行されるとき、Mono はその関数をコンパイルし、Mono.JIT はこのコンパイルのオーバーヘッドを示します。 |
UnsafeUtility.Malloc | UnsafeUtility.Malloc を呼び出し、アンマネージメモリを割り当てるサンプルが含まれます。ガベージコレクターはこのメモリを追跡しませんが、メモリの割り当てはパフォーマンスに大きな影響を与える可能性があり、このサンプルでそれが示されています。この呼び出しのソースを調べるには、Profiler ウィンドウで、このマーカーの コールスタック 記録を有効にします。 |
これらのマーカーには、消費された CPU サイクルを測定するのではなく、スレッドの同期やジョブシステムに関連する情報を強調するサンプルが含まれます。これらのサンプルが表示されたら、CPU Profiler モジュールの Timeline ビュー を使って、他のスレッドで同時に発生していることを確認してください。
マーカー | 機能 |
---|---|
Idle | ワーカースレッドが非アクティブになっている時間の長さを示すサンプルが含まれます。ワーカースレッドは、ジョブシステムがそれを利用しないときは常に非アクティブであり、待機モードになり、セマフォを待機します。 アイドルサンプル間の小さなギャップは、通常、ジョブシステムがサンプルを起こすとき (例えば、新しいジョブをスケジュールするときなど) に発生します。長いギャップは、実装されていないネイティブジョブがスレッド上で実行されていることを示している場合があります。 |
JobHandle.Complete | ジョブの同期ポイントが発生したときのサンプルが含まれます。同期ポイントが発生すると、アプリケーションのパフォーマンスに影響を与えたり、マルチスレッドのジョブコードの実行に支障をきたす場合があります。同期ポイントが発生した場所を正確に見つけやすくするために、このサンプルの コールスタック の記録を有効にします。CPU Profiler モジュールの Timeline ビューで Show Flow Events を選択すると、現時点でどのジョブが終了したかを確認できます。 |
Semaphore.WaitForSignal | スレッドの同期ポイントを示すサンプルが含まれます。待機しているスレッドを見つけるには、タイムラインビューでこのサンプルの直前に終了したサンプルを確認してください。 |
WaitForJobGroupID | JobHandle の同期フェンスがトリガーされました。これは、ワークスチール を引き起こす可能性があります。これは、ワーカーが作業を終了し、他のワーカージョブが完了するのを確認するときに発生します。これらは、このマーカーで実行されるジョブサンプルとして表示されます。“スチール” されたジョブは、必ずしも待たれていたジョブというわけではありません。 |
以下の表は、高レベルの物理演算プロファイラーマーカーの一部をまとめたものです。FixedUpdate は、これらの計測をすべて呼び出します。
マーカー | 機能 | |
---|---|---|
Physics.FetchResults | 物理エンジンから物理シミュレーションの結果を収集するサンプルが含まれます。接触ストリーム、トリガーのオーバーラップ、ジョイントの破損イベントなど。 | |
Physics.Interpolation | Physics.Interpolation メソッドの実行時間を計測するサンプルが含まれます。このメソッドは、アプリケーションのすべての物理オブジェクトの位置と回転の補間を管理します。 | |
Physics.Processing | すべてのスレッドで物理シミュレーションが完了するまで、メインスレッドで待機して時間を費やしたサンプルが含まれます。アプリケーションが Physics.Processing に多くの時間を費やしているにも関わらず、シーンの物理関連のゲームオブジェクトが数個しかない場合、ワーカースレッドがジョブスチーリングによって他のシステムのタスクを拾い、物理関連として報告した可能性があります。これは、待機中に、メインスレッドが優先度の高いキューからジョブを拾うためです。 | |
Physics.ProcessingCloth | Physics.ProcessingCloth メソッドの実行時間を計測したサンプルが含まれます。このメソッドは、すべてのクロスの物理ジョブを処理します。このサンプルを展開すると、物理エンジンの内部で行われる作業の低レベルの詳細が表示されます。 | |
Physics.ProcessReports | OnTriggerEnter などのコールバックで物理データのスクリプトへの転送に費やす時間に該当するサンプルが含まれます。ノート: これらのサンプルは、FetchResults の間にすでに準備されているため、必要なデータを計算しません。 4 つの異なるサブステージがあります。 |
|
Physics.Contacts | Physics.Contacts の実行時間を測定するサンプルが含まれます。OnCollisionEnter、OnCollisionExit、OnCollisionStay イベントを処理します。 | |
Physics.JointBreaks | Physics.JointBreaks の実行時間を計測するサンプルが含まれます。壊れたジョイントに関連する更新やメッセージを処理します。 | |
Physics.TriggerEnterExits | Physics.TriggerEnterExits の実行時間を計測するサンプルが含まれます。OnTriggerEnter と OnTriggerExit イベントを処理します。 | |
Physics.TriggerStays | Physics.TriggerStays の実行時間を計測するサンプルが含まれます。OnTriggerStay イベントを処理します。 | |
Physics.Simulate | Physics.Simulate メソッドの必要条件の作業時間を計測するサンプルが含まれます。このメソッドは物理エンジンにシミュレーションの実行を指示し、現在の物理計算の状態を更新します。 | |
Physics.UpdateBodies | すべての物理関連ボディの位置と回転を更新するサンプルが含まれます。Rigidbody コンポーネントを持つ各ゲームオブジェクトに対して、このマーカーを持つサンプルが、物理エンジンからポーズを読み取り Transform に書き込みます。 | |
Physics.UpdateCloth | Physics.UpdateCloth メソッドの実行時間を計測するサンプルが含まれます。このメソッドは、クロスとそのスキンメッシュに関連する更新を処理します。 |
スクリプトのライフサイクル内のスクリプトのライフサイクルと一般的なサンプルについては、イベントの実行順序 のドキュメントを参照してください。
CPU Profiler は、いくつかの一般的なパフォーマンス問題を検出し、警告を発します。これらは、モジュールの詳細ペインの CPU Profiler モジュールの Hierarchy ウィンドウの Warning 列に表示されます。
プロファイラーは、パフォーマンスに重要なコンテキストで避けるべき特定の呼び出しを検出します。以下のように、操作がパフォーマンスに影響を与えている理由とともに警告を表示します。
警告 | 説明 |
---|---|
Animation.DestroyAnimationClip Animation.AddClip Animation.RemoveClip Animation.Clone Animation.Deactivate |
RebuildInternalState がトリガーされたことを示します。RebuildInternalState は、Animation コンポーネントの各クリップのカーブのリストを確認し、各カーブをゲームオブジェクトのコンポーネントの値に再度紐づけする操作です。 この操作はリソースを大量に消費するため、ランタイムにこれらのメソッドを呼び出すことは、できるだけ避けてください。 |
AssetBundle.asset/allAssets | AssetBundle の読み込みが完了していない状態 (AssetBundleRequest.isDone が false) で Unity が AssetBundleRequest.assets/allAssets API を呼び出したことを示します。これにより、メインスレッドでストール (stall) が発生し、読み込み操作が完了するのを待機します。 |
AsyncUploadManager.AsyncBufferResized AsyncUploadManager.AsyncBufferDelete |
GPU にデータをアップロードするための内部バッファが十分な大きさでないためにサイズ変更されることを示しています。このサイズ変更には時間がかかり、CPU アクティビティのスパイクの原因になります。 前もって大きなサイズを割り当てるメモリの余裕があれば、この警告を避けることができます。 Quality Settings の Async Upload Buffer Size を使って、デフォルトのサイズを設定できます。 AsyncUploadManager.AsyncBufferResized マーカーは、デフォルトのバッファサイズの目安として使用する、新しく割り当てられたサイズを示します。 |
Rigidbody.SetKinematic | Rigidbody 用の非凸のメッシュコライダーを再作成します。 |