dtraceのバッファまわりなど

dtraceのバッファまわりに関して資料を読んだので、その概要をまとめておく。

主バッファ
主バッファとは、トレースアクションがデフォルトで使用するバッファ。
主バッファはCPUごとに割り当てられる。
主バッファには、バッファの使われ方を示す「ポリシ」がある。

(1)switchポリシ
CPU 単位でバッファのペアを割り当てるポリシ。
ペアの片方はアクティブなバッファ、もう片方は非アクティブなバッファ。
DTrace コンシューマバッファの読み取りを試みたときカーネルは以下2点を行う。
(1)非アクティブなバッファとアクティブなバッファの切り替え
(2)元々アクティブであったバッファの内容をDTrace コンシューマにコピーする

なお、このポリシでは、アクティブなバッファに収まりきらない量のデータをトレースしようとした場合、そのデータは欠落となり、CPU 単位の欠落カウントが増分されることに注意する。

(2)fillポリシ
このポリシでは、CPUごとの主バッファーの少なくとも1つがいっぱいになったと見なされた時点で、明示的にトレースを停止する。

(3)ringポリシ
主バッファはリングバッファ。主バッファがいっぱいになった場合、一番古いものが上書きされる。

投機トレース
一時的にトレースバッファとは別の場所にデータをトレースしておき、あとで「破棄」(discard)するか、トレースバッファに「コミット」(commit)するのかを決めることができる。
これによって、本当に欲しいデータのみをトレースバッファに保存できるため、大量のトレースデータに埋もれずに済む。

使い方としては....
(1)speculation()をコールし、投機用のバッファを割り当て識別子を取得する。
ちょうどopen()のようなイメージだと思う。
(識別子は、スレッドローカル変数にでも保存しておくのが良い)

(2)投機バッファにトレースデータを保存する場合、speculate()を呼び出す。
これは「以後の節内の処理でのトレースデータの保存先を(1)で割り当てた投機バッファにする」ことを意味する。
speculate()の引数は、(1)で取得した識別子である。

(3)投機バッファの中身をコミットしたい場合はcommit()を、破棄したい場合はdiscard()をそれぞれ呼び出す。
これら2関数の引数は両方共、(1)で取得した識別子である。