Low-Level Memory Tracker

Unreal プロジェクトのメモリ使用量をトラックします。

Low-Level Memory Tracker (LLM トラッカー) とは、Unreal Engine (UE) プロジェクトでのメモリ使用量をトラックするツールです。LLM では、スコープ付きのタグ システムを使用して、Unreal Engine と OS によってアロケートされたすべてのメモリの記録を維持します。LLM は、Unreal Engine がサポートするすべてのプラットフォームに対応しています。

LLM トラッカー

現在 LLM には 2 つのトラッカーがあり、それぞれには独自のアロケーション マップとタグ スタックが備わっています。「デフォルト トラッカー」は、エンジンからのすべてのアロケーションに対応します。これは 2 つのうちのレベルが高いほうで、FMemory クラス関数の Malloc を通じて行われたアロケーションを記録します。このトラッカーにより、stat LLMstat LLMFULL のコンソール コマンドに統計情報が供給されます。レベルが低いほうのトラッカーは「プラットフォーム トラッカー」と呼ばれ、OS によるアロケーションをすべて記録します。たとえば、Binned2 といった関数による内部アロケーションがトラックされます。したがって、デフォルト トラッカーの統計情報は、プラットフォーム トラッカーの統計情報のサブセットということになります。

LLM 設定

プロジェクトで LLM を有効にするには、次のコマンドライン引数とコンソール コマンドを使用します。

コマンドライン引数

説明

-LLM

LLM を有効にします。

-LLMCSV

すべての値を継続的に CSV ファイルに書き出します。-LLM が自動的に有効になります。

-llmtagsets=Assets

実験的機能です。各アセットによってアロケートされる合計を表示します。

-llmtagsets=AssetClasses

実験的機能です。各 UObject クラス タイプの合計を表示します。

コンソール コマンド

説明

stat LLM

LLM の概要を表示します。すべての低レベルのエンジン統計情報は、単一の Engine 統計情報にまとめられます。

stat LLMFULL

すべての LLM 統計情報を表示します。

stat LLMPlatform

OS からアロケートされたすべてのメモリの統計情報を表示します。

stat LLMOverhead

LLM によって内部で使用されるメモリ量を表示します。

-LLMCSV コマンドライン引数を使った場合は .CSV ファイルが「saved/profiling/llm/」に書き出されます。このファイルには、現在値を MB 単位で示す、タグごとの列が含まれています。デフォルトで、新しい行が 5 秒ごとに書き込まれます。この頻度は、LLM.LLMWriteInterval コンソール変数を使って変更できます。

LLM タグ

エンジンによるすべてのメモリ アロケーション (ゲーム コードを含む) には、属するカテゴリを識別するタグ値が割り当てられます。つまり、すべてのメモリは一度だけトラックされて、そこから漏れたり、複数回カウントされたりすることはありません。すべてのカテゴリの合計は、ゲームで使用されるメモリ量の合計になります。

タグは、タグ-スコープのマクロを使って適用されます。このスコープ内で行われるアロケーションには指定したタグが与えられます。LLM によってタグ スコープのスタックが維持され、一番上のタグがアロケーションに適用されます。LLM 統計情報は、stat LLM または stat LLMFULL のコンソール コマンドを使ってゲーム内に表示できます。各タグの現在の合計が MB 単位で表示されます。また、LLM によって統計値が .CSV ファイルに書き出されるため、それらの値を分析することもできます。現在エンジン内にあるタグ カテゴリは次のとおりです。

タグ名

説明

UObject

これには、UObject から継承するあらゆるクラスと、そのクラスによってシリアル化されたあらゆるもの (プロパティを含む) が含まれます。UObject は、他のカテゴリでトラックされていないすべてのエンジンとゲーム メモリに対応します。この統計情報には、個別にトラックされるメッシュやアニメーションのデータは含まれていません。統計情報は、レベル内に配置されたオブジェクトの数に基づいています。

EngineMisc

他のカテゴリでトラックされない低レベル メモリです。

TaskGraphTasksMisc

独自のカテゴリを持たないタスク グラフから開始されるタスクです。全般的には低レベルになります。

StaticMesh

UStaticMesh クラスと関連するプロパティです。実際のメッシュ データは含まれません。

カスタム タグ

Unreal Insights を使ってプロジェクトのメモリ使用量をプロファイリングする際に、Memory Insights 内で「LLM Untracked (LLM トラッキングなし)」とタグ付けされたアロケート済みのメモリがある場合があります。LLM_DECLARE_TAGLLM_DEFINE_TAG のマクロを使ってカスタム タグを作成することで、トラックされていないメモリ アロケーションを検出しやすくなります。これらのマクロはエンジン ファイルの変更を必要とせず、ゲーム モジュールまたはプラグイン内で実行できます。作成したカスタム タグを使用するには、LLM_SCOPE_BYTAG マクロを使用します。手順は次のとおりです。

  1. ヘッダ ファイル内のカスタム LLM タグを LLM_DECLARE_TAG で宣言します。

  2. LLM_DEFINE_TAG を使い、関連する .cpp ファイル内でカスタム LLM タグを定義します。

  3. メモリ使用量をトラックするスコープを示す LLM_SCOPE_BYTAG.cpp ファイル内で LLM_SCOPE_BYTAG とともに使用します。

カスタム タグの宣言と使用に関する例については、後述の「」を参照してください。

カスタム タグのマクロ

LLM_DECLARE_TAG

LLM_DECLARE_TAG マクロでは、別の場所で定義されて LLM_SCOPE_BYTAG で使用可能なタグ、または他の LLM_SCOPE で名前で参照可能なタグを宣言します。

  • パラメータ

    • UniqueName:名前で参照するためのタグの名前です。LLM_DEFINE_TAGLLM_SCOPE、または ELLMTag に渡されるタグの中で固有の名前にする必要があります。

LLM_DEFINE_TAG

LLM_DEFINE_TAG マクロでは、LLM_SCOPE_BYTAG で使用可能なタグ、または他の LLM_SCOPE で名前で参照可能なタグを定義します。

  • パラメータ

    • UniqueNameWithUnderscores:タグの名前の変更版です。名前による参照で使用されます。LLM_DEFINE_TAGLLM_SCOPE、または ELLMTag に渡されるすべてのタグの中で固有である必要があります。LLM_DEFINE_TAG では、親の通常のセパレータ (/) を (_) に置き換える必要があります。

    • DisplayName:(任意) UniqueName を使用する親または NAME_None がある場合に、親の名前に (/) で参加したタグのトレース時に表示する名前です。

    • ParentTagName:(任意) 親がない場合に、親タグまたは NAME_None の固有の名前になります。

    • StatName:(任意) LLM データをフレームごとに発行する際に、このタグの量とともに入力する統計情報の名前です。統計情報を入力しない場合は NAME_None を使用します。

    • SummaryStatName:(任意) LLM データをフレームごとに発行する際に、このタグの量に加える統計情報グループの名前です。統計情報グループを加えない場合は、NAME_None を使用します。

CustomTagExample.h

#pragma once
...
LLM_DECLARE_TAG(MyTestTag);

CustomTagExample.cpp

LLM_DEFINE_TAG(MyTestTag);

AMyActor::AMyActor()
{
    LLM_SCOPE_BYTAG(MyTestTag);
    MyLargeBuffer.Reset(new uint8[1024*1024*1024]);
}

タグ セット (実験的機能)

タグ セットを使用するには、LLM_ALLOW_ASSETS_TAGS を「LowLevelMemTracker.h」内で定義します。タグ セットを使用する際は、それぞれのアロケーションによってアセット名またはオブジェクト クラス名が追加で格納されます。

タグ セットを使用することで、メモリ使用量とランタイム パフォーマンスの両方に追加のオーバーヘッドが生じます。

実装の技術的詳細

LLM は、ポインタによってインデックス化されるすべてのアロケーションのマップを維持することで動作します。現在、マップには各アロケーションのサイズと、割り当てられたタグが含まれます。ゲームでは一度に 400 万にも及ぶライブ アロケーションが生じることがあるため、メモリのオーバーヘッドをできる限り少なく保つことが重要になります。現在の実装では、一つのアロケーションに 21 バイトを使用します。

アロケーション

サイズ

ポインタ

8 バイト

ポインタのハッシュ キー

4 バイト

サイズ

4 バイト

タグ

1 バイト

ハッシュ マップ インデックス

4 バイト

OnLowLevelAlloc 関数を使ってアロケーションをトラックする場合は、タグ スタックの一番上にあるタグが現在のタグになり、そのポインタをキーとしてアロケーション マップに格納されます。コンテンションを避けるために、各タグのフレームのデルタが個別の FLLMThreadState クラス インスタンスでトラックされます。フレームの終わりにこれらのデルタが合算されて、その結果が統計情報システムと .CSV ファイルに発行されます。

LLM は非常に早い段階で初期化されるため、これをデフォルトで有効にしておく必要があります。コマンドラインで LLM が有効になっていない場合は、LLM が自身をシャットダウンしてすべてのメモリをクリーンアップし、オーバーヘッドが生じないようにします。この場合、LLM はテスト ビルドとシッピング ビルドから完全に除外されます。

LLM は統計情報システムなしでも実行できます。たとえば、テスト コンフィグの場合などです。画面上に統計情報を表示することはできませんが、.CSV ファイルには統計情報が書き出されます。LLM は、「LowLevelMemTracker.h」ファイルの ENABLE_LOW_LEVEL_MEM_TRACKER を変更して有効にする必要があります。

タグは、スコープ マクロを使って適用されます。主なマクロとして次の 2 つがあります。

  • LLM_SCOPE(Tag)

  • LLM_PLATFORM_SCOPE(Tag)

これらは、それぞれデフォルト トラッカーとプラットフォーム トラッカーの現在のスコープを設定します。こうしたスコープにはプラットフォームに依存するバージョンがあり、たとえば、プラットフォーム固有のタグ列挙型を使う LLM_SCOPE_[Console](Tag) があります。LLM_SCOPED_TAG_WITH_STAT などの統計情報を使うスコープ マクロは、現時点では非推奨であるため使用しないでください。

LLM 内部で使用するすべてのメモリは、プラットフォームにより供給される LLMAlloc 関数と LLMFree 関数によって管理されます。LLM が自身のメモリ使用量をトラックしないように (そして無限再帰呼び出しを生じないように)、LLM では他の方法でアロケーションを行わないようにすることが重要です。

追加の技術的詳細

このセクションでは、LLM を使用する際に知っておくべきさまざまな注意事項や追加情報を示します。

  • LLM のオーバーヘッドは 100MB 以上になることがあるため、各コンソールの大きなメモリ モードで実行することを強くお勧めします。

  • テスト コンフィグの LLM では統計情報ページを画面に表示しませんが、.CSV ファイルには書き出されます。シッピングでは LLM は完全に無効になります。

  • アセット タグのトラッキングについてはまだ早期実験段階にあります。

Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
キャンセル