5 バッファおよびバッファリング
データのバッファリングと管理は、dtraceコマンドのようにDTraceフレームワークがクライアントに提供する主要なサービスです。この章では、データのバッファリングの詳細と、DTraceのバッファ管理ポリシーを変更するための各種オプションについて説明します。
主バッファ
デフォルトでは、主バッファは、トレース・アクションがデータを記録するバッファであり、DTraceの呼出し時に必ず使用されます。これらのアクションには、printa
、printf
、stack
、trace
およびtracemem
があります。
主バッファは常にCPU単位で割り当てられます。このポリシーはチューニングできません。ただし、cpu
オプションを使用して、トレースやバッファ割当てが単一のCPUで行われるようにすることは可能です。
主バッファのポリシー
DTraceでは、カーネル内の高度に制約されたコンテキストでトレースを実行できます。特に、カーネル・ソフトウェアが確実にメモリーを割り当てられないような状況でトレースできます。このように、コンテキストに柔軟性があるため、使用できる空間がないときでも、データのトレースが試行される可能性があります。DTraceには、そのような状況の発生時に対処するためのポリシーが必要です。ただし、特定の実行文のニーズに基づいてポリシーをチューニングすることもできます。ときには、新しいデータを破棄するポリシーが必要になる場合もあります。また、最も古いデータが記録されている空間を再利用して、新しいデータのトレースを有効化する必要が生じることもあります。ほとんどの場合、必要とされるのは、使用できる空間にできるかぎり不足が生じないようにするポリシーです。このような様々な要求に対応するため、DTraceでは、複数の異なるバッファ・ポリシーを使用できます。このためには、bufpolicy
オプションを実装し、コンシューマ単位で設定できるようにします。詳細は、「オプションおよびチューニング可能パラメータ」を参照してください。
switchポリシー
主バッファには、デフォルトでswitch
バッファ・ポリシーがあります。このポリシーでは、CPU単位のバッファのペアが割り当てられ、ペアの一方はアクティブであり、もう一方はアクティブでないバッファです。DTraceコンシューマがバッファを読み取ろうとすると、カーネルは最初に、アクティブでないバッファとアクティブなバッファを切り替えます。バッファの切替えは、ウィンドウ内のトレース・データが失われる可能性がない状態で行われます。バッファの切替えが完了すると、新たにアクティブでなくなったバッファがDTraceコンシューマにコピーされます。このポリシーによって、コンシューマが常に自己矛盾のないバッファを認識することが確実化されます。バッファのトレースとコピーが同時に行われることはないことに注意してください。この方法で、時間ウィンドウ内でのトレースの一時停止や、トレース不能状態の発生を回避することもできます。バッファの切替えと読取りのレートは、switchrate
オプションにより、コンシューマ側で制御されます。switchrate
では、その他のレート・オプションと同じく、任意の時間接尾辞を指定できますが、デフォルトでは、秒当たりのレートが設定されます。switchrate
とその他のオプションの詳細は、「オプションおよびチューニング可能パラメータ」を参照してください。
switch
ポリシーでは、指定の有効なプローブがアクティブな主バッファ内の使用可能な空間より多いデータをトレースしようとすると、そのデータが欠落し、CPU単位の欠落カウントが増分されます。1つ以上の欠落が発生した場合は、dtraceにより、次のようなメッセージが表示されます。
dtrace: 11 drops on CPU 0
合計バッファ・サイズより指定のレコードが大きい場合、バッファ・ポリシーに関係なくレコードは欠落します。欠落の発生を予防するには、bufsize
オプションで主バッファのサイズを大きくするか、switchrate
オプションで切替えレートを上げます。
switch
ポリシーでは、DTraceサブルーチンに対するスクラッチ・メモリーがアクティブなバッファから割り当てられます。
fillポリシー
ある問題に対して、単一のカーネル内バッファを使用する場合もあります。これは、switch
ポリシーと適切なD構造体を使用して、Dの変数を増分し、exit
アクションを適切な述語に付加するとで実現できますが、この方法では、欠落が発生する可能性が残ります。単一の大きいカーネル内バッファをリクエストし、CPU単位のバッファが1つ以上占有されるまでトレースを続行するには、fill
バッファ・ポリシーを使用します。このポリシーでは、有効なプローブが主バッファの残りの空間に収まらない量のデータをトレースしようとするまで、トレースが続行されます。空間が不足すると、バッファがいっぱいになったとみなされ、コンシューマに、CPU単位のバッファが1つ以上占有されたことが通知されます。dtraceが満杯になったバッファを検出すると、トレースは停止し、すべてのバッファが処理された後、dtraceが終了します。バッファに入るデータがあっても、いっぱいになったバッファにはそれ以上トレースされません。
fill
ポリシーを使用するには、bufpolicy
オプションにfill
を設定します。たとえば、次のコマンドは、バッファ・ポリシーをfill
に設定し、CPU単位の2KBのバッファに、すべてのシステム・コール・エントリをトレースします。
# dtrace -n syscall:::entry -b 2k -x bufpolicy=fill
fillポリシーおよびENDプローブ
END
プローブは通常、DTraceコンシューマによってトレースが明示的に停止されるまで起動しません。END
プローブは必ず、単一のCPU上でのみ起動しますが、プローブが起動するCPUは定義されていません。fill
バッファを使用している場合、CPU単位の1つ以上の主バッファがいっぱいになったとみなされた時点で、明示的にトレースが停止します。fill
ポリシーを選択した場合、END
プローブは、いっぱいになったバッファがあるCPU上でも起動します。fill
バッファへのEND
のトレースを可能にするため、DTraceは、END
プローブが消費する見込みの空間の量を計算し、主バッファのサイズからこの空間の量を減算します。結果が負の数になった場合、DTraceは起動せず、dtraceは次のエラー・メッセージを出力します。
dtrace: END enablings exceed size of principal buffer
予約機構によって、いっぱいになったバッファでも、END
プローブ用の空間は必ず残されています。
ringポリシー
DTraceのring
バッファ・ポリシーは、障害を引き起こすイベントをトレースする場合に役立ちます。障害の再現に時間がかかるときは、最新のデータのみを保存したい場合があります。主バッファがいっぱいになると、トレースは最初のエントリに戻り、最も古いトレース・データが上書きされます。ringバッファを使用するには、次のようにbufpolicy=ring
を指定します。
# dtrace -s foo.d -x bufpolicy=ring
ringバッファを作成する場合は、dtraceでは処理が終了するまで何も出力されません。ringバッファはその時点で消費され、処理されます。dtraceコマンドでは各ringバッファをCPU順に処理します。CPUのバッファ内のトレース・レコードは、古いものから順に並んでいます。switch
バッファリング・ポリシーの場合と同じく、CPUの異なるレコード間の順序付けは行われません。このような順序付けが必要な場合は、トレースのリクエストの一部として、timestamp
変数をトレースする必要があります。
次の例では、#pragma option
ディレクティブを使用してringバッファリングを有効にします。
#pragma D option bufpolicy=ring #pragma D option bufsize=16k syscall:::entry /execname == $1/ { trace(timestamp); } syscall::exit:entry { exit(0); }
バッファ・サイズ
各バッファのサイズは、コンシューマ単位でチューニングできます。次の表に示すように、バッファ・サイズのチューニング用オプションが別途用意されています。
バッファ | サイズ・オプション |
---|---|
集積体 |
|
主 |
|
投機 |
|
これらのオプションには、サイズを表す値を設定します。その他のサイズ・オプションと同じく、値にはサイズ接尾辞が付けられる場合があります。詳細は、「オプションおよびチューニング可能パラメータ」を参照してください。
たとえば、次のようにして、dtraceのコマンドラインからバッファ・サイズを10MBに設定します。
# dtrace -P syscall -x bufsize=10m
または、-bオプションをdtraceコマンドに指定して使用できます。
# dtrace -P syscall -b 10m
また、次のように、pragmaを使用してbufsize
を設定することもできます。
#pragma D option bufsize=10m
選択したバッファ・サイズは各CPU上のバッファ・サイズを示します。switch
バッファ・ポリシーでは、bufsize
は各CPU上の各バッファのサイズを示します。デフォルトのバッファ・サイズは4MBです。
バッファ・サイズの変更ポリシー
使用可能なメモリー容量が十分ではない、またはDTraceコンシューマがチューニング可能な制限値(「オプションおよびチューニング可能パラメータ」を参照)を超えたため、システムのカーネルの空きメモリー容量が不足したため、必要なサイズのバッファを割り当てられないことがあります。バッファ割当てエラーのポリシーは、bufresize
オプション(デフォルト値はauto
)で設定できます。auto
バッファ・サイズ変更ポリシーでは、正常に割当てが行われるまで、バッファのサイズが2等分されます。次の例のように、割当てバッファのサイズがリクエストされたサイズより小さい場合、dtraceはメッセージを生成します。
# dtrace -P syscall -b 4g dtrace: description 'syscall' matched 430 probes dtrace: buffer size lowered to 128m ...
または、次のようなメッセージが生成されます。
# dtrace -P syscall'{@a[probefunc] = count()}' -x aggsize=1g dtrace: description 'syscall' matched 430 probes dtrace: aggregation size lowered to 128m ...
バッファ割当てのエラー発生後に、bufresize
をmanual
に設定して、手動での調整を要求することもできます。このポリシーでは、割当てエラーが発生すると、DTraceが起動しなくなります。
# dtrace -P syscall -x bufsize=1g -x bufresize=manual dtrace: description 'syscall' matched 430 probes dtrace: could not enable tracing: Not enough space #
主バッファ、投機バッファ、集積体バッファを含むすべてのバッファのサイズ変更ポリシーは、bufresize
オプションで指定します。