XRay フライトデータレコーダトレースフォーマット

バージョン:

2017-07-20 時点で 1

はじめに

XRay トレースをフライトデータレコーダーモードで収集する場合、アプリケーションの各スレッドはトレースデータで満たすバッファを要求し、ある時点で確定され、フラッシュされます。

プロファイラの目標はオーバーヘッドを最小限に抑えることであり、フラッシュされたデータはバッファに直接対応します。

このドキュメントでは、トレースファイルのフォーマットについて説明します。

概要

各トレースファイルは、特定のスレッドにおける一連のイベントに対応します。

ファイルには、ヘッダーの後に、区別されたレコードタイプのシーケンスが続きます。

バイトフィールドのエンディアンは、トレースファイルを生成したプラットフォームのエンディアンと一致します。

ヘッダーセクション

トレースファイルは 32 バイトのヘッダーで始まります。

フィールド

サイズ (バイト)

説明

version

2

4

バージョン化されたリーダーを想定しています。このドキュメントでは、version == 1 の場合のフォーマットについて説明します。

2

type

4

4

トレースのタイプをエンコードする列挙型。フライトデータレコーダーモードのトレースは type == 1 です。

bitfield

8

4

バイトにアラインされていないパラメータを保持します。以下で詳しく説明します。

8

cycle_frequency

8

8

イベントの期間をティックで測定するために使用される CPU オシレータの周波数 (ヘルツ)。

buffer_size

フィールド

8

説明

ヘッダーに続くトレースのデータ部分のサイズ (バイト)。

1

reserved

8

1

将来の使用のために予約されています。

8

30

ファイルヘッダーの bitfield パラメータは、以下のフィールドで構成されています。

サイズ (ビット)

説明

constant_tsc

1

  • イベント間のティックを記録するために使用されるプラットフォームのタイムスタンプカウンターが、CPU 周波数の変化にもかかわらず一定の周波数でティックするかどうか。 0 == 非定数。 1 == 定数。

  • nonstop_tsc

  • 1

  • CPU が低電力状態にあるかどうかにかかわらず、tsc がカウントを続けるかどうか。 0 == 停止。 1 == 継続。

(残り30ビット)

意味がありません。

データセクション

フィールド

8

説明

トレースのヘッダーに続いて、ヘッダーの buffer_size フィールドと一致するサイズのデータセクションがあります。

1

データセクションは、異なるタイプの要素のストリームです。

シーケンスには、いくつかのカテゴリのデータがあります。

3

関数レコード: 関数レコードには、関数の実行開始と終了のタイミングが含まれます。関数レコードはそれぞれ 8 バイトです。

メタデータレコード: メタデータレコードは多くの目的に使用されます。主に、関数ごとに記録するにはコストがかかりすぎる可能性がありますが、きめ細かいタイミングをコンテキスト化するために必要な情報をキャプチャします。また、ユーザー定義のイベントデータペイロードのマーカーとしても使用されます。メタデータレコードはそれぞれ 16 バイトです。

28

イベントデータ: 自由形式のデータは、バイナリによってトレースされ、ハンドラ関数によって定義されたデータをエンコードするイベントに関連付けられる可能性があります。イベントデータの前には常に、そのサイズを示すマーカーレコードが付きます。

関数引数: 一部の関数の引数はトレースに含まれています。これらは、ポインタアドレスまたはプリミティブであり、高級言語での型とは無関係に読み取られ、ログに記録されます。トレーサーにとって、これらはすべて数値です。引数が添付されている関数レコードは、関数エントリレコードにその存在を示します。引数ゼロから始まる連続した関数引数シーケンスのロギングのみをサポートしています。これは、メンバー関数呼び出しの「this」ポインタになります。たとえば、最初と3番目の引数のロギングはサポートしていません。

32

メモリフォーマットのリーダーは、ステートマシンを維持する必要があります。フォーマットはアラインメントのためのパディングを行わず、シークできません。

関数レコード

関数レコードは 8 バイトのレイアウトです。このレイアウトは、計装された関数のコールスタックとその期間を再構築するための情報をエンコードします.

フィールド

サイズ (ビット)

説明

説明

discriminant

0

1

リーダーが関数レコードまたはメタデータレコードを読み取る必要があるかどうかを示します。関数レコードの場合は0に設定します。

1

action

3

2

関数が開始されているか、終了されているか、最適化によって生成された非標準のエントリまたは終了かを示します。

function_id

3

28

関数の数値 ID。xray 計装マップを介して名前に解決されます。計装マップは、コンパイル時に xray によってオブジェクトファイルに構築され、関数 ID をアドレスにペアリングします。パッチ用およびバイナリシンボルを検索して名前を取得するためのルックアップとして使用されます。

tsc_delta

32

前回のレコードがデルタまたはその他の TSC リセットイベントを記録してからのタイムスタンプカウンターのティック数。

リトルエンディアンマシンでは、ビットフィールドは最下位ビットから最上位ビットの順に並べられます。リーダーは 8 ビット値を読み取り、判別子にマスク 0x01 を適用できます。同様に、32 ビットを読み取り、0x04 だけ右に符号なしシフトして function_id フィールドを取得できます。

フィールド

ビッグエンディアンマシンでは、ビットフィールドは最上位ビットから最下位ビットの順に書き込まれます。リーダーは 8 ビット値を読み取り、判別子の 7 ビットだけ右に符号なしシフトします。 function_id フィールドは、32 ビット値を読み取り、マスク 0x0FFFFFFF を適用することで取得できます.

説明

トレースのヘッダーに続いて、ヘッダーの buffer_size フィールドと一致するサイズのデータセクションがあります。

関数の動作タイプは次のとおりです.

タイプ

番号

説明

Entry

0

典型的な関数エントリ。

Exit

1

説明

サイズ (ビット)

0

典型的な関数終了。

1

Tail_Exit

2

2

3

末尾呼び出しの最適化による関数の終了。

4

Entry_Args

5

4

6

引数を記録する関数エントリ

Entry_Args レコードには、引数自体は含まれていません。代わりに、ログに記録された各引数のメタデータレコードが、ストリーム内の関数レコードの後に続きます.

メタデータレコード

バッファ全体に 16 バイトのメタデータレコードが散在しています。通常、計装されたバイナリの場合、関数レコードよりもまばらになり、バイナリ実行状態の全体像を提供します.

フィールド

サイズ (バイト)

説明

メタデータレコードのレイアウトはレコードに部分的に依存しますが、共通の構造を共有しています.

2

関数レコードについて説明したのと同じビットフィールドルールが、MetadataRecords の最初のバイトに適用されます。このバイト内では、リトルエンディアンマシンは lsb から msb の順序を使用し、ビッグエンディアンマシンは msb から lsb の順序を使用します.

8

13

フィールド

サイズ

説明

バッファ全体に 16 バイトのメタデータレコードが散在しています。通常、計装されたバイナリの場合、関数レコードよりもまばらになり、バイナリ実行状態の全体像を提供します.

フィールド

サイズ (バイト)

説明

discriminant

8

1 bit

リーダーが関数レコードまたはメタデータレコードを読み取る必要があるかどうかを示します。メタデータレコードの場合は1に設定します。

4

record_kind

8

3

フィールド

7 bits

メタデータレコードのタイプ。

data

バッファ全体に 16 バイトのメタデータレコードが散在しています。通常、計装されたバイナリの場合、関数レコードよりもまばらになり、バイナリ実行状態の全体像を提供します.

フィールド

サイズ (バイト)

説明

15 bytes

2

レコードタイプごとに異なる方法で使用されるデータフィールド。

列挙型レコードの種類の表を次に示します。

8

種類

8

5

フィールド

番号

NewBuffer

0

バッファ全体に 16 バイトのメタデータレコードが散在しています。通常、計装されたバイナリの場合、関数レコードよりもまばらになり、バイナリ実行状態の全体像を提供します.

フィールド

サイズ (バイト)

説明

列挙型レコードの種類の表を次に示します。

8

EndOfBuffer

8

7

フィールド

1

NewCPUId

2

TSCWrap

フィールド

サイズ (バイト)

説明

3

8

WallTimeMarker

8

7

フィールド

4

XRayは、カスタムイベントをログに記録する機能を提供します。これは、RPCのトレース情報や、アプリケーション固有の同様のトレースデータを記録するために活用できます。

カスタムイベント自体は、バッファ内で任意のサイズを持つ、構造化されていない(アプリケーション定義の)メモリセグメントです。それらの前には、CustomEventMarkerが存在とサイズを示します。

CustomEventMarkerデータセグメント

フィールド

サイズ (バイト)

説明

event_size

4

先行するイベントのサイズ。

列挙型レコードの種類の表を次に示します。

8

イベントのタイムスタンプカウンター。

8

3

フィールド

バッファの終わりレコード

バッファの終わりレコードタイプは、このバッファにトレースデータがこれ以上ないことを示します。リーダーは、バッファの開始前に示された残りのbuffer_sizeをスキップし、別のヘッダーまたはEOFを探す必要があります。

フォーマット文法と不変条件

メタデータレコードと関数レコードのすべてのシーケンスが有効なデータであるとは限りません。シーケンスは状態マシンとして解析する必要があります。有効な形式の要件は、文脈自由文法として表現できます。

これは、EBNF形式のステートメントでフォーマットを説明しようとする試みです。

  • Format := Header ThreadBuffer* EOF

  • ThreadBuffer := NewBuffer WallClockTime NewCPUId BodySequence* End

  • BodySequence := NewCPUId | TSCWrap | Function | CustomEvent

  • Function := (Function_Entry_Args CallArgument*) | Function_Other_Type

  • CustomEvent := CustomEventMarker CustomEventUnstructuredMemory

  • End := EndOfBuffer RemainingBufferSizeToSkip

関数レコードの順序

関数レコードに期待されることを理解するのに役立つ、いくつかの明確化があります。

  • Exitを持つ関数は、トレース内で対応するEntryまたはEntry_Args関数レコードが先行している必要があります。

  • Tail_Exit関数レコードは、プログラムカウンタが取る戻りアドレスを持つ関数の関数IDを記録します。つまり、末尾呼び出しの最適化が使用されなかった場合、呼び出しスタックからポップされる最後の関数です。

  • インストルメンテーションの対象としてマークされているすべての関数が、必ずしもトレースにあるとは限りません。トレーサーは、重要でない関数のトレースを保持するためにヒューリスティックを使用します。

  • すべてのエントリに、トレースされたExitまたはTail Exitがある必要はありません。バッファの容量が不足したり、インストルメント化された関数が終了する前に、プログラムがトレーサーにバッファを返すためのファイナライズを要求する可能性があります。