BLOGブログ

2020.04.08UE4UE/ C++

[UE4] Statコマンドに情報を追加しよう

皆さん!計測してますかー!

計測といっても時間だけでしょうか?処理負荷=処理にかかった時間ですので主に時間計測をイメージするか思います。
ですが、処理に失敗した回数、存在するアクターの数、それらの最大・最小・平均値と様々情報を取得できるとより、
処理の現状を把握することができます。
これらの統計情報を確認するためにStat コマンドをつかうのですが、独自に計測情報を追加することができます。
今回はその追加方法について触れたいと思います。

Statコマンド

参考ページ
https://docs.unrealengine.com/ja/Engine/Performance/StatCommands/index.html

基本的に標準で用意されている情報で様々な統計情報を確認することができます。
自分でSTAT グループを追加することで、標準で用意されているStatコマンド以外に追加することができます。

実装方法

Statのグループの作成
書式
DECLARE_STATS_GROUP(GroupDesc, GroupId, GroupCat)
引数
GroupDesc グループ名(テキスト形式)
GroupId グループの ユニークID STATGROUP_XXX形式で指定してください。
    ※ここの「XXX」は Statコマンドの引数に渡す文字にもなります。
GroupCat 将来の使用のために予約されています。(STATCAT_Advancedを入れておけばOKです)


DECLARE_STATS_GROUP(TEXT(“StatTest”),STATGROUP_StatTest, STATCAT_Advanced);
この宣言をしてコンパイルし、「Stat StatTest」コマンドを実行するとそのグループに属した情報が表示されます。

Statの計測項目の宣言

統計情報の集める形式にはいくつか種類があります。
Cycle Counter
主に処理時間計測に使用 呼び出し回数もカウントします。
関数スコープ内の処理を計測する形式と、計測の開始と終了を任意で呼び出す手法があります。
Float/Dword Counte
フレームごとにクリアされるカウンターです。
1フレーム中に起きている情報を集計する場合に使用します。
Float/Dword Accumulator
フレームごとにクリアされずに、任意でリセット可能なカウンターです。
フレームをまたいで、情報を集計する場合はこちらを使用します。
Memory
メモリ用に最適化された特殊なカウンター、Accumulatorと同じくフレーム毎にクリアされない。
・桁数によりキロ、メガ 表記になる。
・メモリアロケータの種類を管理できる(物理メモリ、GPU、テクスチャプール等)

宣言方法
統計情報を使用するためには予めIDの宣言をする必要があります。

DECLARE_CYCLE_STAT(CounterName, StatId, GroupId)
引数
CounterName 表示される名前
StatId スタットのID(ユニークID)
GroupId グループID

各カウンターの宣言マクロ
Cycle Counter
DECLARE_CYCLE_STAT(CounterName, StatId, GroupId)
Float型(内部的にはdouble 型 (8 バイト) がベースとなっています)
DECLARE_FLOAT_COUNTER_STAT(CounterName, StatId, GroupId)
DWord 型
DECLARE_DWORD_COUNTER_STAT(CounterName, StatId, GroupId)
Float型 Accumulator
DECLARE_FLOAT_ACCUMULATOR_STAT(CounterName, StatId, GroupId)
Dword側 Accumulator
DECLARE_DWORD_ACCUMULATOR_STAT(CounterName, StatId, GroupId)
メモリ用
DECLARE_MEMORY_STAT(CounterName, StatId, GroupId)
メモリ用 メモリプール指定有り
DECLARE_MEMORY_STAT_POOL(CounterName, StatId, GroupId, Pool)
プールを使用するメモリ カウンターを宣言します。
Poolにはどのプールであることを定義できます。

複数のCPPファイルにまたぐ場合
先程紹介した、宣言用のマクロは1つのCPPファイル内だけ使用する場合にしか使用できません。
externバージョンを使用してください。各マクロに_EXTERNが追加されたバージョンを使用してください。
DECLARE_CYCLE_STAT_EXTERN(CounterName, StatId, GroupId, API)
DECLARE_FLOAT_COUNTER_STAT_EXTERN(CounterName, StatId, GroupId, API)
DECLARE_DWORD_COUNTER_STAT_EXTERN(CounterName, StatId, GroupId, API)
DECLARE_FLOAT_ACCUMULATOR_STAT_EXTERN(CounterName, StatId, GroupId, API)
DECLARE_DWORD_ACCUMULATOR_STAT_EXTERN(CounterName, StatId, GroupId, API)
DECLARE_MEMORY_STAT_EXTERN(CounterName, StatId, GroupId, API)
DECLARE_MEMORY_STAT_POOL_EXTERN(CounterName, StatId, GroupId, Pool, API)

使用方法
関数スコープ内時間の計測
SCOPE_CYCLE_COUNTER(StatId);
関数スコープ内(中括弧{}の区間)の時間を計測します。

使用例

カウンター操作
時間計測以外のカウンターの値の統計を取りたい場合は以下のマクロを使用してください。

カウンターのインクリメント(1増やす)
INC_DWORD_STAT(StatId)
カウンターのデクリメント(1減らす)
DEC_DWORD_STAT(StatId)

指定した値分カウンターを増やす
DWORD型
INC_DWORD_STAT_BY(StatId, Amount)
Float型
INC_FLOAT_STAT_BY(StatId, Amount)
メモリ
INC_MEMORY_STAT_BY(StatId, Amount);

指定した値分カウンターを減らす
DWORD型
DEC_DWORD_STAT_BY(StatId, Amount)
Float型
DEC_FLOAT_STAT_BY(StatId, Amount)
メモリ
DEC_MEMORY_STAT_BY(STAT_PixelBufferMemory,NumBytes);

カウンターの値を設定
DWORD型
SET_DWORD_STAT(StatId, Value)
Float型
SET_FLOAT_STAT(StatId, Value)
メモリ
SET_MEMORY_STAT(StatId, Value);

UE4の標準機能で十分間に合う部分もあるのですが、
ゲームやプラグイン固有の情報を集めるために可視化してみてはいかがでしょうか?