投機
DTraceには、1つ以上のプローブの場所で暫定的にデータをトレースするために使用できる投機トレース機能が含まれています。 その後、別のプローブの場所でプリンシパルのバッファにデータをコミットするように決定できます。 投機は、対象とする出力のみが含まれたデータをトレースするために使用できます。追加の処理は不要で、DTraceのオーバーヘッドが最小化になります。
投機は次の方法で達成されます:
- 一時的な投機バッファを設定します
- 推測バッファにトレースする1つ以上の句の指示
- 投機バッファ内のデータを主バッファにコミットするか、投機バッファを破棄します。
句内の適切な関数を使用して、特定の条件が満たされたときに投機データをコミットまたは破棄できます。 投機を使用すると、条件が満たされるまで一連のプローブのデータをトレースして、データが有用でない場合は廃棄することも、そうでない場合は保持することもできます。
次の表では、DTraceの投機関数について説明します。
表4-14 DTrace投機関数
| 関数 | 引数 | 説明 |
|---|---|---|
|
なし |
新しい投機バッファの識別子を返します |
|
|
ID |
これ以降の節の部分については、指定されたIDの投機バッファにトレースすることを示します。 |
|
|
ID |
IDに関連付けられている投機バッファをコミットします。 |
|
|
ID |
IDに関連付けられている投機バッファを破棄します。 |
例4-1 憶測の使い方
次の例は、投機の使用方法を示しています。 投機の正しい動作には、すべての投機関数が一緒に使用されている必要があります。
投機はsyscall::open:entryプローブに対して作成して、投機のIDはスレッド・ローカル変数にアタッチします。 open()システム・コールの最初の引数は、printf関数を使用して投機バッファにトレースされます。
syscall::open:returnプローブには、さらに3つの節が含まれています。 それらの節の最初で、投機バッファにerrnoをトレースします。 2番目の節の述語では、ゼロ以外のerrno値をフィルタ処理して、投機バッファをコミットします。 3番目の節の述語では、ゼロのerrno値をフィルタ処理して、投機バッファを破棄します。
プログラムの出力は主データ・バッファに返されるため、open()システム・コールが失敗すると、プログラムは実質的にファイル名とエラー番号を返します。 このコールが失敗しない場合は、投機バッファにトレースされた情報が破棄されます。
syscall::open:entry
{
/*
* The call to speculation() creates a new speculation. If this fails,
* dtrace will generate an error message indicating the reason for
* the failed speculation(), but subsequent speculative tracing will be
* silently discarded.
*/
self->spec = speculation();
speculate(self->spec);
/*
* Because this printf() follows the speculate(), it is being
* speculatively traced; it will only appear in the primary data buffer if the
* speculation is subsequently committed.
*/
printf("%s", copyinstr(arg0));
}
syscall::open:return
/self->spec/
{
/*
* Trace the errno value into the speculation buffer.
*/
speculate(self->spec);
trace(errno);
}
syscall::open:return
/self->spec && errno != 0/
{
/*
* If errno is non-zero, commit the speculation.
*/
commit(self->spec);
self->spec = 0;
}
syscall::open:return
/self->spec && errno == 0/
{
/*
* If errno is not set, discard the speculation.
*/
discard(self->spec);
self->spec = 0;
}