# Dynamic Instrumentation of Production Systems **著者**: Bryan M. Cantrill · Michael W. Shapiro · Adam H. Leventhal([[Sun Microsystems]] Solaris Kernel Development) **発表**: USENIX Annual Technical Conference 2004 (General Track)、Boston, MA、2004-06-27 **URL**: https://www.usenix.org/legacy/event/usenix04/tech/general/full_papers/cantrill/cantrill.pdf --- ## 概要 本論文は [[DTrace]] を発表した一次ソースである。DTrace は Solaris に統合された動的計装フレームワークであり、**本番稼働中**のシステムに対してユーザー空間・カーネル空間の双方を、(1) 無効時ゼロ・プローブ効果、(2) 絶対的安全性、(3) 任意の述語とアクション、(4) スケーラブルな集約という 4 原則のもとで計装できる。従来の静的計装・プロセス中心ツールでは診断不能だったシステミック性能問題を本番で特定した事例も報告する。 --- ## 背景と問題意識 システムが大規模化・複雑化するにつれ、性能分析は開発者による開発環境ではなく、**システムインテグレーターによる本番環境**で行われるようになった。コンポーネント化とアプリケーション統合の進展により、元の開発者が想定しなかった組み合わせが生じ、既存の計装基盤は開発者・開発環境に向けて設計されたままとなった。 本番用途に設計されたツールであっても大半がプロセス中心であり、ユーザー空間とカーネル空間にまたがる **システミック(systemic)な問題**の診断には使えなかった。本番用の性能分析基盤には次の 2 要件が必須となる。 1. **ゼロ・プローブ効果(zero probe effect)**: 無効時はシステムに一切の性能影響を与えない。偶発的な操作でシステム障害を引き起こさない絶対的安全性。 2. **システミックスコープ**: システム全体が計装可能で、データを横断的に集約できる機能。 --- ## アーキテクチャ ### プロバイダとプローブ DTrace の計装は**プロバイダ**(ロード可能カーネルモジュール)が担う。プロバイダは DTrace カーネルモジュールの API を通じてプローブを作成する。プローブは ``` < provider, module, function, name > ``` の 4 タプルで一意に識別される。プローブの作成は計装自体ではなく「計装の可能性の登録」であり、コンシューマが明示的に有効化するまで一切の影響がない。有効化時には **ECB(Enabling Control Block)** が生成され、プローブ発火時の処理チェーンを定義する。 ### DIF (D Intermediate Format) 述語とアクションはカーネル内の仮想マシン命令セット DIF にコンパイルされる。DIF は 64 ビットレジスタ・算術/論理演算・前向き分岐のみ(無限ループ不可)・メモリロードの安全検査を備えた RISC 命令セットであり、安全なカーネル内エミュレーションのために設計されている。 ### バッファリング コンシューマごとに CPU ローカルのバッファが割り当てられ、割り込み無効化下でアクティブ/インアクティブバッファを切り替えるロックフリー機構により、データ整合性とウェイトフリー処理を両立する。 --- ## プロバイダ群 | プロバイダ | 計装手法 | 特徴 | |---|---|---| | FBT (Function Boundary Tracing) | 命令書き換え(SPARC: ba,a / x86: トラップ) | 25,000 以上のカーネル関数エントリ・リターン | | SDT (Statically-defined Tracing) | no-op 書き換え | 意味的なプローブ名を静的宣言でき、オーバーヘッドは無視できるレベル | | lockstat | 同期プリミティブ動的書き換え | カーネルロック競合の完全可視化 | | syscall | システムコールテーブル書き換え | アプリのシステム呼び出し動作を追跡 | | profile | 時間ベース割り込み | 非同期サンプリングで任意のシステム状態を観測 | | pid | 任意命令のトラップ置換 | ユーザープロセスの任意アドレスを計装 | --- ## D 言語 D は C に準拠した制御言語であり、すべての ANSI C 演算子・バックティック記法によるカーネル名前空間アクセス・以下の変数スコープをサポートする。 - **グローバル変数**: 全 CPU/スレッドで共有 - **クロース局所変数** (`this->`): 1 クロース実行内で再利用 - **スレッド局所変数** (`self->`): OS スレッド単位のプライベートストレージ - **連想配列**: タプルキーによるオンデマンド生成の辞書型 D プログラムは awk に似た「プローブ記述 / 述語 / アクション」の宣言的クロース構造を持ち、パターンマッチングプログラムとして動作する。 --- ## 集約 (Aggregation) 集約関数は `f(f(x₀)∪...∪f(xₙ)) = f(x₀∪...∪xₙ)` を満たす関数として定義される(count/max/sum 等)。DTrace はソースで集約を計算し、CPU ローカルな中間値を保持してから結合することで、(1) 保存データ量を大幅削減、(2) 共有データ構造を避けてスケーラブルに動作する。 ``` @count[execname] = count(); # アプリ名ごとの write(2) 呼び出し数 @[pid, arg4] = quantize(arg2); # mmap の fd・サイズ分布 ``` 集約関数 `quantize()` は 2 の冪分布を出力し、大量データの傾向を視覚的に把握できる。 --- ## 投機的トレース (Speculative Tracing) 散発的な異常では、プローブ発火時点では「その記録が必要か」を判断できない。投機的トレーシングは一時バッファにデータを記録しておき、後から**コミット**または**破棄**を決定する機構である。これにより大量の後処理フィルタリングが不要になる。 ``` self->spec = speculation(); # 投機バッファ割り当て speculate(self->spec); # 以降の記録を投機バッファへ commit(self->spec); # 確定 → メインバッファへ移動 discard(self->spec); # 破棄 ``` --- ## ユーザー空間計装 (pid プロバイダ) `pid` プロバイダは特定プロセスの任意命令をトラップ置換で計装する。対象プロセスを再起動せず計装でき、カーネルプローブとまったく同じ DTrace 機構(述語・アクション・集約・スレッド局所変数)を適用できる。ユーザー/カーネル境界をまたいで制御フローとデータフローを追跡できることが、DTrace のシステミックな可視化を実現する核心である。 --- ## 本番事例:SunRay サーバの性能問題 **環境**: 10 CPU・32 GB メモリ・約 170 SunRay ユーザーが接続するサーバ(Broomfield, Colorado) **診断の流れ**: 1. `mpstat(1M)` でクロスコール数の異常を観測 → DTrace `sysinfo:::xcalls` で「Xsun が犯人」を特定 2. スレッド局所変数で Xsun のどのシステムコールがクロスコールを誘発しているかを追跡 → `munmap(2)` が毎秒数千回 3. `mmap(2)` の PID・ファイルディスクリプタ集約 → fd=4 (`/dev/zero`) に集中し、170 X サーバのうち 6 本が突出 4. ユーザースタックトレース集約 → 全 mmap が Pixmap 生成コールパス 5. `sched:::wakeup` プローブで mmap 後に wakeup されるプロセスを集約 → `gtik2_applet2` が 6399 件でトップ(次点は 549 件) 6. `gtik2_applet2` が X グラフィクスコンテキスト(GC)を 10 ミリ秒ごとに生成・破棄していることを確認 **結果**: 6 インスタンスの `gtik2_applet2` を停止すると、クロスコール 64% 減・非自発的コンテキストスイッチ 35% 減・システム時間 27% 減・ユーザー時間 37% 減・アイドル 15% 増という劇的な改善を達成。 **重要性**: このような**システミックな問題**は、特定プロセスだけを見る従来ツールでは診断不能だった。gtik2_applet2 自体はほとんど仕事をしておらず、その影響が他コンポーネントへ波及していた。DTrace の集約・スレッド局所変数・ユーザー/カーネル統合計装がなければ特定できなかった。 --- ## 関連研究との比較 | 系統 | 代表例 | DTrace との差異 | |---|---|---| | 拡張型 OS | VINO, SPIN | 汎用拡張だが「理解するための」プリミティブが少ない | | 静的計装 | ATOM, Purify, LTT | 本番不可(バイナリ差し替えまたは要再起動)、限定的なプローブ | | Linux 動的 | DProbes | ロスあり・スレッド局所変数なし・集約なし・安全性不十分 | | 研究カーネル | K42 | データ整合性を犠牲にした scalable tracing | | 動的計装ツール | Kerninst | 安全性担保なし(誤使用でパニック) | DTrace の独自貢献: スレッド局所変数・連想配列・データ集約(rudimentary 以上)・投機的トレース。 --- ## 影響と後継 DTrace は Solaris での統合後(2004)、次のような影響をもたらした。 - **OS 移植**: FreeBSD・macOS・NetBSD へ移植 - **eBPF の思想的先祖**: Linux の eBPF は DTrace の概念(プローブ・安全な検証・カーネル内プログラム実行)を Linux ネイティブで再実装したもの。[[eBPF]] の設計哲学はゼロ・プローブ効果と安全性という DTrace 原則を受け継ぐ。 - **オブザーバビリティ文化**: 本番計装の「安全性ファーストかつゼロコスト原則」が現代 [[オブザーバビリティ]] の礎石となった。 --- ## 主要引数 | 主張 | 根拠(論文中) | |---|---| | 無効時ゼロ・プローブ効果 | SDT マクロを 150 か所追加しても差異を計測不能(§4.2) | | 安全な DIF | 前向き分岐のみ・実行時エラーを報告・ページ障害ハンドラ修正による安全なロード(§3.5) | | 本番適用の実証 | 10 CPU SunRay サーバで gtik2_applet2 特定・停止後 64% クロスコール削減(§9) | --- ## 関連 - 概念: [[DTrace]] / [[動的インストルメンテーション]] / [[プローブ効果]] / [[オブザーバビリティ]] / [[eBPF]] / [[継続的プロファイリング]] - エンティティ: [[Bryan Cantrill]] / [[Michael Shapiro]] / [[Adam Leventhal]] / [[Sun Microsystems]] - 関連 MOC: [[AI Infra Telemetry - MOC]] ## 出典 - 一次ソース: `.raw/papers/cantrill.pdf` - URL: https://www.usenix.org/legacy/event/usenix04/tech/general/full_papers/cantrill/cantrill.pdf