Unreal Engine 5 (UE5) では Unreal Insights の機能が拡張され、改善されたメモリ トラッキングとプロファイリング向けのサポートが「Memory Insights」機能に追加されました。これによりデベロッパーは、任意の時点でメモリの各ブロックに関連付けられた Low Level Memory (LLM) タグ やコールスタックなど、メモリの割り当てと解放に関する情報をさらに詳細に確認できるようになりました。 Memory Insights が備えるクエリ システムを利用すると、特定の時点でのライブ割り当てを見つけて、メモリ使用量の増減を確認し、短期と長期の割り当てを区別して、メモリリークを発見できます。
セッションをレコーディングする
Memory Insights の利用を開始し、メモリ チャンネル内のトレースを記録するには、以下の手順に従います。
Unreal Insights を実行またはビルドする
[Start (スタート)] > [Command Prompt (コマンド プロンプト)] に移動し、以下を入力します。
Engine\Binaries\Win64\UnrealInsights.exe
または、「Engine\Binaries\Win64
」フォルダに移動し、「UnrealInsights.exe
」をダブルクリックすることでも実行できます。
メモリ トレーシングを使用してゲーム プロジェクトを実行する
オペレーティング システムから コマンド プロンプト を起動し、次のプロジェクト サンプルを実行します。
cd C:\MyEngineInstallLocation\
Samples\Games\MyGameSample\Binaries\Win64\MyGameSample.exe -trace=default,memory
プロジェクトのセッションをレコーディングするには、プロセスの最初からメモリ トレース チャンネルを有効にしておく必要があります。そうしないと、遅延接続セッションで割り当てイベントのトレーシングを開始することはできません。さらに、パッケージ化されたプロジェクトでトレースを実行している場合は、開発 モードでパッケージ化されていることを確認する必要があります。
trace コマンド metadata
と assetmetadata
を使用すると、アセット名とクラス名に追加のフィルタリング オプションを用意できます。たとえば、アセットごとやクラス名ごとにメモリ アロケーションの負荷を計算できます。
Samples\Games\MyGameSample\Binaries\Win64\MyGameSample.exe -trace=default,memory,metadata,assetmetadata
Insights セッション ブラウザからトレースを開く
Unreal Insights セッション ブラウザに戻って、Unreal Engine の [Timing Insights (タイミング インサイト)] ウィンドウでの分析のために .utrace
ファイルをダブルクリックして開きます。[Menu (メニュー)] > [Memory Insights (メモリ インサイト)] を選択し、[Memory Insights] ウィンドウを開きます。
メモリ割り当て - グラフ トラック
Unreal Insights では、プロジェクトに割り当てられているメモリの分析を提供するために、各割り当てイベントの完全なコールスタックをキャプチャします。Memory Insights のメイン インターフェースには、セッション中のメモリ使用に関する概要を示すタイムラインが表示されます。
[Main Memory Graph (メイン メモリ グラフ)] には、プロジェクトで追跡したメモリの総量が表示されます。これには、LLM から収集した各タグの情報が含まれます。さらに、ライブ割り当ての合計数を示す次のグラフがあります。
グラフ タイプ | 色 | 説明 |
---|---|---|
合計割り当て済みメモリ | 青 | 詳細な割り当ての追跡に基づいて、各時点で割り当てられたメモリの合計量を表示します。 |
ライブ割り当て数 | 黄 | 任意の時点でのアクティブな割り当ての総数を表示します。 |
割り当て/解放イベント数 | 緑/オレンジ | 単位あたりの割り当てイベント数および解放イベント数を示します。これは、時間の「スライス」として表されます。 |
これらの各グラフは、詳細な割り当ての追跡に基づいています。追跡は、時間値 0 から開始され、約 1ms の詳細度があります。LLM プレフィックス タグ (RenderTargets、SceneRender、UObject) があるその他のグラフは、Low-Level Memory トラッキング ランタイム システムに基づいています。
これらのタグは、セッションが開始して数秒してからトラッキングを開始し、フレーム単位の詳細度があります。
デフォルトでは、4096 の割り当て/空きイベントごとに 1 つのタイムスタンプを発行します。必要に応じて、Engine/Source/Runtime/Core/Private/ProfilingDebugging/MemoryAllocationTrace.cpp
にある MarkerSamplePeriod を変更することにより、この量を変更できます。たとえば、この変数の値を 0 に設定すると、割り当て/解放イベントが発生するごとに 1 つのタイムスタンプが発行されます。
Memory Insights のタイムラインは、[Timing View (タイミング ビュー)] へのトラックのオーバーレイをサポートしています。 Memory Insights ビューには、[Timing (タイミング)]、[Investigation (調査)]、[LLM Tags (LLM タグ)]、および [Modules (モジュール)] の 4 つのパネルが表示されます。
Timing View
[Timing] をクリックして、[Timing View] ウィンドウの表示を切り替えることができます。ここでは、メモリ使用率に関連するさまざまなトラックのパフォーマンス データを観察およびフィルタできます。
Investigation パネル
[Investigation] パネルでは、割り当てに関するさまざまなクエリを実行できます。
Low-Level Memory (LLM) Tags
[LLM Tags] では、さまざまな LLM タグの可視性を制御します。このデータは、使用しているオペレーティング システムから直接トレースされます。
LLM タグ、アセット および ソース ファイル を次のようにグループ化できます。
Modules
コール スタック シンボルが解決されると、その結果がキャッシュ ファイルに格納されます。これらのファイルは、[Modules (モジュール)] をクリックすることで表示できます。このパネルでは、古いトレース ファイルを開いて、シンボルを使用できます。
Discovered、Cached、Resolved、および Failed となっているシンボルの数の列を確認できます。失敗したリスト アイテムが赤色で強調表示され、正しく解決されたリスト アイテムは緑色で強調表示されます。黄色は一部のシンボルが解決され、一部が失敗したことを示しています。
以前のメモリ トラッキングのランタイムの実装は、フォルダ「Engine\Source\Runtime\Core\Public\HAL\LowLevelMemTracker.h
」内の LowLevelMemTracker クラスに実装されています。[LLM Tags] パネルと LLM グラフの両方で、このシステムから直接トレースされたデータが使用されています。詳細な割り当てデータは、別の固有のトレースの実装から取得されます。
Memory Insights には、新しいクエリ機能と追跡されたメモリ割り当て情報が含まれます。特定の時間枠 (ある瞬間の前後) に UE5 が割り当て/解放を行ったメモリ ブロックを特定したり、メモリリークを確認したりできます。クエリ システムにアクセスするには、トレース ログを開いて [Investigation] タブに移動します。
[Investigation] - 割り当てのクエリ
タイムラインにメモリ使用率の概要が示されると同時に、「クエリ」を使用することで、一定の時間範囲にわたる個々の割り当ての振る舞いが評価されます。クエリ は、ルール と、「A」や「B」ラベルなどの タイムスタンプ (複数可) によって定義されます。
使用可能な クエリ ルール は次のとおりです。
クエリ ルール | 時間変数 | 説明 |
---|---|---|
Active Alloc (アクティブな割り当て) | A | A 時点でのアクティブな割り当てをすべて表示します。 |
Before (前) | A | A 時点前のすべての割り当てを表示します。 |
After (後) | A | A 時点後のすべての割り当てを表示します。 |
Decline (減少) | A と B | A 時点前に割り当てられて、A 時点と B 時点の間に解放されたすべての割り当てを表示します。 |
Growth (増加) | A と B | A 時点と B 時点の間に割り当てられて、B 時点後に解放されたすべての割り当てを表示します。 |
Growth Vs Decline (増加と減少) | A と B | 「growth」割り当て (時間 A と時間 B の間に割り当てられ、時間 B の後に解放される) と「decline」割り当て (時間 A の前に割り当てられ、時間 A と時間 B の間に解放される) を特定します。 「decline」割り当ては負のサイズになるよう変更されているので、サイズの集計では A と B でバラつきがあります。 このクエリの結果は、時間 A に割り当てられた内容と時間 B に割り当てられた内容の比較になります。 タグまたはコール スタックによるメモリ割り当てのグループ化では、グループごとのバラつき (B - A) が示されます。 |
Free Events (解放イベント) | A と B | A 時点と B 時点の間に解放されたすべての割り当てを表示します。 |
Alloc Events (割り当てイベント) | A と B | A 時点と B 時点の間に割り当てられたすべての割り当てを表示します。 |
Short Living Allocs (短寿命の割り当て) | A と B | A 時点後に割り当てられて、B 時点前に解放されたすべての割り当てを表示します。このルールは、スタック割り当ての可能性がある割り当てを特定する際にも使用できます。つまり、これによって一時的または短寿命の割り当てが特定されます。 |
Long Living Allocs (長寿命の割り当て) | A と B | A 時点前に割り当てられて、B 時点後に解放されたすべての割り当てを表示します。 |
Memory Leaks (メモリリーク) | A、B、および C | A 時点と B 時点の間に割り当てられて、C 時点後まで解放されなかったすべての割り当てを表示します。レベルの遷移中など、特定の時点で解放される予定のメモリを特定する際に便利です。 |
Limited Lifetime (限定された存続期間) | A、B、および C | A 時点と B 時点の間に割り当てられて、B 時点と C 時点の間に解放されたすべての割り当てを表示します。 |
Decline of Long Living Allocs (長寿命の割り当ての減少) | A、B、および C | A 時点前に割り当てられて、B 時点と C 時点の間に解放されたすべての割り当てを表示します。 |
Specific Lifetime (特定の存続期間) | A、B、C、および D | A 時点と B 時点の間に割り当てられて、C 時点と D 時点の間に解放されたすべての割り当てを表示します。 |
クエリを作成するには、ルールを選択して、タイムライン内のラベル付きマーカーを目的の位置にドラッグするか、[Investigation] タブ内で時間を指定します。
目的のルールと時間を選択したら、[Investigation] タブの [Run Query (クエリを実行)] ボタンをクリックしてクエリを実行します。
クエリとキャプチャするデータ セットによっては、クエリの実行に長時間かかる場合があります。
割り当ての詳細ビュー
クエリを実行すると新しいウィンドウが表示され、クエリが完了した際にその結果が割り当てテーブルに表示されます。デフォルトでは、この結果はフラット リストの形式で表示されます。
それぞれの割り当ては、その Count (カウント)、Size (サイズ)、LLM Tag (LLM タグ)、Callstack Size (コールスタック サイズ)、割り当てを行った Function (ファンクション) とともに表示されます。
関数名または情報アイコン上にマウス カーソルを合わせると、追加情報と完全なコール スタックが表示されます。
ソート
テーブルのヘッダをクリックすることで、リストをさまざまな列でソートできます。
列のソート | 説明 |
---|---|
Allocation Hierarchy (割り当て階層) | 割り当てツリーの階層でソートします。 |
Allocation Count (割り当て数) | 割り当て数でソートします。 |
Size (サイズ) | 割り当てサイズでソートします。 |
LLM Tag (LLM タグ) | 割り当ての LLM タグでソートします。 |
Function (Callstack) (関数 (コールスタック)) | 割り当てのコールスタックの解決済みの上位の関数でソートします。 |
CallStack Size (コールスタックのサイズ) | コールスタック フレームの数。 |
Grouping (グループ化)
割り当てをグループにまとめるには、[Preset (プリセット)] オプションを使用できます。
プリセット オプション | 説明 |
---|---|
Default (デフォルト) | デフォルトの割り当てを表示します。 |
Detailed (詳細) | ツリー ビューで割り当ての詳細情報を表示するよう設定します。 |
Heap (ヒープ) | さまざまなタイプのメモリの使用方法を調査します。「複数のアドレス空間」を参照してください。 |
Size (サイズ) | 大規模な割り当てをすばやく見つけることができます。 |
Tags (タグ) | 割り当てをシステム別に表示します。 |
Asset (アセット) | アセットタグごとの割り当ての内訳が表示されるようにツリー ビューを設定します。 |
Class Name (クラス名) | クラス名ごとの割り当ての内訳が表示されるようにツリー ビューを設定します。 |
Callstack (コールスタック) | 割り当ての発生元のコールスタックを調査します。 |
Inverted Callstack (反転コールスタック) | ツリー ビューで割り当ての詳細を反転コールスタック別に表示するよう設定します。 |
Address(4k Page) (アドレス (4k ページ)) | 割り当てをそのアドレスに基づいて 4K アライメントのメモリ ページにグループ化します。
|
[Hierarchy (階層)] に移動して [All (すべて)] をクリックするとドロップダウン メニューが表示され、ここでデフォルトの フラット ビュー から別のグループ化オプションに変更することができます。
次のオプションのリストから階層をグループ化できます。
階層グループ | 説明 |
---|---|
Flat (フラット) | すべての項目を含む単一のグループを作成します。 |
Size (サイズ) | サイズに基づいて割り当てをグループ化します。 |
Tag (タグ) | タグ階層に基づいてツリーを作成します。 |
Callstack (コールスタック) | 各割り当てのコールスタックに基づいてツリーを作成します。 |
Inverted Callstack (反転コールスタック) | 各割り当てのコールスタックに基づいてツリーを作成します。 |
Heap (ヒープ) | ヒープに基づきツリーを作成します。 |
Unique Values - Event Distance (固有値 - イベント距離) | イベント距離の値ごとにグループを作成します |
Unique Values - Start Time (固有値 - 開始時間) | 開始時間の値ごとにグループを作成します |
Unique Values - End Time (固有値 - 終了時間) | 終了時間の値ごとにグループを作成します |
Unique Values - Duration (固有値 - 期間) | 期間の値ごとにグループを作成します |
Unique Values - Address (固有値 - アドレス) | 各アドレスの値ごとにグループを作成します |
Unique Values - Memory Page (固有値 - メモリ ページ) | メモリ ページの値ごとにグループを作成します。 |
Unique Values - Size (固有値 - サイズ) | サイズ値ごとにグループを作成します |
Unique Values - LLM Tag (固有値 - LLM タグ) | LLM タグ値ごとにグループを作成します |
Unique Values - Asset (固有値 - アセット) | アセット値ごとにグループを作成します |
Unique Values - Class Name (固有値 - クラス名) | クラス名の値ごとにグループを作成します |
Unique Values - Top Function (固有値 - 最上位関数) | 最上位関数の値ごとにグループを作成します |
Unique Values - Top Source File (固有値 - 最上位ソース ファイル) | 最上位ソースファイルの値ごとにグループを作成します |
Unique Values - Callstack Size (固有値 - コールスタック サイズ) | コールスタック サイズの値ごとにグループを作成します |
Path Breakdown - LLM Tag (パスのブレークダウン - LLM タグ) | LLM タグの文字列型の値の構造体からツリー階層を作成します。 |
Path Breakdown - Asset (パスのブレークダウン - アセット) | アセット タグ文字列型の値の構造からツリー階層を作成します。 |
Path Breakdown - Top Source File (パスのブレークダウン - 最上位ソース ファイル) | 最上位ソース ファイルの文字列型の値の構造体からツリー階層を作成します。 |
詳細フィルタリング
検索テキスト ボックスでは、階層ノードのテキストに基づいて結果を迅速にフィルタする方法を利用できます。クエリによって生成された割り当てのセットは、検索テキスト ボックスの横の Filter Configurator をクリックしてさらにフィルタを適用し、割り当てのグループを分離できます。
グループや、AND/OR キーワードを使用し、詳細なクエリを構築することもできます。
コールスタック シンボル解決
プログラム カウンター アドレスを使用することで、プロジェクトからの コールスタック シンボル トレーシング を実行できます。解析では、対応するソース ファイルに関する情報とともに、これらのアドレスを読み取り可能な文字列に解決する必要があります。
これには、Memory Insights でデバッグ情報を含む正しいバージョンのファイル (プラットフォームに応じて) .pdb
または .elf
ファイルにアクセスできる必要があります。Insights では、次のリストに従って正しいファイルを検索します。
-
このセッション中にユーザーによって入力された新しいパス。
-
実行可能ファイルのパス (一部のプラットフォームで利用可能な場合。これはコンパイルされてバイナリになる)。
-
UE_INSIGHTS_SYMBOLPATH
環境変数からのパス。この変数は、セミコロン区切りのパスを受け入れます。 -
ユーザー コンフィギュレーション ファイルからのパス。
すべてのシンボルが解決されると、その結果がキャッシュ ファイルに格納されます。これらのファイルは、[Modules] パネルをクリックすると表示できます。続いて、選択したファイルを右クリックし、ドロップダウン メニューから以下のうち 1 つを選択すると、これらのファイルを開くことができます。
これにより、トレース ファイルを他のユーザーに送信する方法が提供されます。このデバッグ情報へのアクセス権は不要です。
ロード方法 | 説明 |
---|---|
Load symbols from file (ファイルからシンボルをロード) | ファイルを指定して、モジュールのシンボルをロードします。成功した場合、同じディレクトリから他の失敗したモジュールのロードを試みます。 |
Load symbols from directory (ディレクトリからシンボルをロード) | ディレクトリを指定して、モジュールのシンボルをロードします。成功した場合、同じディレクトリから他の失敗したモジュールのロードを試みます。 |
複数のアドレス空間
メモリ トレーシングでは、さまざまな ヒープ のメモリをトラックします。概念上、あらゆる割り当ては ルート ヒープ に属しており、一つのタイプのメモリを表します。たとえばデスクトップ プラットフォームでは、あるルート ヒープがシステム メモリで、他のものがグラフィック カード上のビデオ メモリである場合があります。それぞれのルート ヒープには独自のアドレス空間があります。 各ルート ヒープでは、割り当てのホストが可能なヒープ割り当てが作成されます。通常、これは割り当てをバックアップする仮想メモリ割り当てを意味しますが、ヒープ割り当てでブロック スタイル アロケータを表すことも可能です。これによって、これらのメモリ ブロックの使用に関する調査が提供されます。