豊岡拓 ftrace snapshotを作った、Kernel 3.9で利用可能になる トレースとは この発表においては、プログラムの実行を理解する上で有益なデータをバッファ等に記録すること 用途 デバッグ 障害解析 常時トレースを動かしておき、システムが停止した時にダンプを用いて理由を解析する 性能解析 どこが時間を食っているのか ボトルネック解析 ftrace カーネルに組み込まれているトレース機構 元々はRTツリーのFunction tracerから始まった (なのでftrace) 現在では様々なトレース機能が統合されている Events Latency 最大の割り込み禁止期間を知りたい Stack Block, mmio Dynamic events 好きなところにbreakpointを設置 Trace Events あらかじめ埋め込まれたトレースポイントを踏んだ時にイベントを記録 現在のLinux Kernelでは500以上が設定されている syscallを含めるともっと Kernelの中のTrace bufferに記録される 記録されるデータ PID CPUID タイムスタンプ イベント名 イベント毎の引数 Kernelsharkというツールで可視化出来る Fedoraには標準である Function Tracer カーネル内の全ての関数呼び出し・リターンを記録出来る コールグラフ、処理時間が分かる Irqsoff Tracer 最大の割り込み禁止区間を検出 「最大で8013us発生したよ」 RTOSだとかなり大きい遅延 ftraceの全体像 hook mechanisms mcount tracepoint kprobes (uprobes) plugin tracers function irqsoff wakeup stack trace trace event common components debugfs I/F ring buffer debugfs経由で操作 /procの様なもの 疑似ファイルをecho, catする trace-cmd /sys/kernel/debug/tracing/ 以下にファイルが出来る current_tracer どのpluginを使うか指定する トレースバッファ ロックレスリングバッファ 記録を読み出しを並行して行える # cat trace するだけでバッファを読み出せる テキスト形式 バッファ内のデータは消費されない 書き込み可能、かつO_TRUNCでopenするとクリア # echo > trace trace_pipe traceに似ている バッファ内のデータを読んだ際に消費する trace_pipe_raw バイナリ形式で生の情報を出力する splice(2)でゼロコピー転送が可能 cpu毎のI/Fしかない 一度に全部のCPUを読み込むことは出来ない options/ options/overwrite バッファが満杯になった時に上書きするか、記録をやめるか 1 -> 古いイベントを捨てる (デフォルト) 0 -> 記録停止 events/ イベントの有効・無効を制御 filter 特定の条件を満たすイベントだけを記録出来る trace_marker ユーザ空間からトレースバッファにイベントを記録する write(2)で好きな文字列を書き込むだけで記録出来る アプリケーションの動作チェックなどに有用 最近入った・入る予定の機能 Kprobes event(2.6.33~) 動いているカーネルに動的に好きな場所にイベントを埋め込める カーネルの改造不要 Uprobes event (2.6.35~) Kprobesのユーザ空間番 アプリケーションの改造不要 Ojbdumpなどでアドレスを持ってくる必要がある Snapshot(3.9~) トレースを止めずに、ある瞬間のバッファのスナップショットを取る機能 予備のトレースバッファを用意しておいて、好きなタイミングで切り替える # echo 1 > snapshot これだけでスナップショットが取られる この際に予備のバッファも割り当てられる バッファの割り当て時間が気になる場合は、あらかじめ1を書いてバッファを確保しておくと良い Multi-buffer(3.10~?) トレースバッファを用途別に複数個使い分ける機能 今までは一つのグローバルバッファしかなかった(せいぜいCPU毎) バッファの個数はmkdir/rmdirで動的に変更可能 # cd instances/; mkdir buf_1 今のところ、Trace Eventsのみ利用可能 Function-trigger 特定の関数が呼ばれた時にアクションを起こす トーレス全体のOn/Off 特定のイベントが呼ばれたらトレースイベントをOn/Off スナップショットを取る スタックトレースを取る # echo 'vfs_read:snapshot:1' > set_ftrace_filter trace_clock タイムスタンプの種類を変更出来る 基本的にはTSCベース local -> CPU間で同期を取らない global -> ロックを取って同期させる counter -> 順番だけを見たい時 x86-tsc (3.8~) -> 生のTSC local/globalはTSCをマイクロ秒などに変更している uptime -> jiffersだけなので軽い perf -> perfと同じタイムスタンプをつける Q/A オーバーヘッドはどれくらいか どれくらいのイベントをOnにするかによる 取りたいイベントをあらかじめOnにして、その後負荷の具合を見ながら調整する 記録する際にロックを取るなどによりメモリ帯域を食ってしまうことはないか 基本的にCPU間でロックを取ることはない(ロックレス)