LinuxにFtraceを導入する

Linuxカーネルを再構築（リビルド）してftraceを有効にする方法について説明します。基本的には必要なカーネルのCONFIGの説明だけです。

#カーネルコンフィグ
ftrace関係の設定項目は、基本的にKernel hackingにあるTracers以下にまとまっています。まずこのTracers(*CONFIG_FTRACE*)を有効にします。
```
[*] Tracers  --->
```
この項目に入ると、色んなオプションがあるのが解ると思います。
一つづつ見ていきましょう。

### Kernel Function Tracer (*CONFIG_FUNCTION_TRACER*)

いわゆる関数コールトレースです。インライン展開されていない実体のある関数の呼び出しを記録することが出来ます。後述する`CONFIG_DYNAMIC_FTRACE`をサポートしているアーキテクチャ(x86,armなどほぼ全て)では、通常使っていない場合はほぼオーバヘッドが0になるので、積極的に有効にしましょう。

### Kernel Function Graph Tracer (*CONFIG_FUNCTION_GRAPH_TRACER*)

関数呼び出しに加えて、関数からの戻りもトレースする機能です。戻り時間を記録することで、対象の関数で実際に消費した時間を計算することができたり、呼び出しのコールスタックの変化を視覚的に楽しむことが出来ます。オススメです。ただしこの機能はarm32のthumbカーネルでは有効に出来ません。気をつけてください。あと、多少余計にメモリを食いますが、トレースバッファに比べたらなんてことはないので気にしなくてもいいです。

### Interrupts-off Latency Tracer (*CONFIG_IRQSOFF_TRACER*)

割り込み禁止区間の長さを記録する機能です。割り込み禁止区間が長く、長時間割り込みが禁止されていると、ハードウェアの制御処理が遅れるなどの問題が起きやすくなります。このトレーサはそうした原因になりそうな実行パスを特定するための機能です。
基本的には割り込み禁止が最大となった処理のスタックトレースを表示し、どの実行パスが原因で遅れたのかを特定するのを助けます。
制御時間のシビアなデバイスなどを作っている場合にはありがたい機能です。
この機能を有効にすると、後述するper-cpuスナップショット機能も有効になります。多少メモリも消費するので気をつけてください。

### Scheduling Latency Tracer (*CONFIG_SCHED_TRACER*)

最も高い優先度のタスクがスケジュール可能となってから、実際にスケジュール(実行)されるまでの遅延時間を記録する機能です。
上記割り込み禁止区間のトレーサと似たような機能ですが、こちらはタスクスケジューリングの確認用です。
この機能を有効にすると、後述するスナップショット機能も有効になります。多少メモリも消費するので気をつけてください。

### Trace syscalls (*CONFIG_FTRACE_SYSCALLS*)

個々のシステムコールをトレースできるようにする機能です。この機能がない場合、全てのシステムコールはraw_syscallという一種類のイベントによりトレースされるため、システムコール毎の引数の解釈が出来ません。
システムコール毎のイベントを定義するため、それなりにリソースを要求しますが、是非有効にすることをおすすめします。

### Create a snapshot trace buffer (*CONFIG_TRACER_SNAPSHOT*)

トレースした情報を貯めるリングバッファのスナップショットを取る機能です。スナップショット機能を使うには、予めトレース用のバッファと同サイズのメモリを割り当てておくことになり、メモリ消費量は増えますので注意が必要です。

#### Allow snapshot to swap per CPU (*CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP*)

CPU毎のスナップショットを取得できるようにします。

### Branch Profiling
if文をトレースし統計を取る機能です。非常にオーバヘッドが大きく、しかも本当に性能の最適化をしたい場合にしか使えない上、最近はCPU自体の分岐予測が高精度になっているため、ほぼ使う必要はない機能です。以下の3つから選択します。

##### No branch profiling (*CONFIG_BRANCH_PROFILE_NONE*)
デフォルトの値です、if文を全くトレースしません。(機能の無効化）

##### Trace likely/unlikely profiler (*CONFIG_PROFILE_ANNOTATED_BRANCHES*)

likely/unlikelyが付いたif文のみトレースします。

##### Profile all if conditionals (*CONFIG_PROFILE_ALL_BRANCHES*)
全てのif文をトレースします。

### Trace max stack (*CONFIG_STACK_TRACER*)

スタックの消費量をトレースし、最も多くスタックを使った処理をスタックトレースとともに記録します。これはスタックオーバフローになりそうな箇所を検出することで、開発者が適切にメモリのアロケーションを行えるようにするための機能です。
デバイスドライバの開発などには便利でしょう。

### Support for tracing block IO actions (*CONFIG_BLK_DEV_IO_TRACE*)

ブロックデバイスのキュー毎のIO処理をトレースするための機能です。[blktrace](https://git.kernel.org/cgit/linux/kernel/git/axboe/blktrace.git/)というツールによって使われますが、ftrace単体でもトレース内容を見ることは可能です。（統計処理などはツールが必要）

### Enable kprobes-based dynamic events (*CONFIG_KPROBE_EVENT*)

kprobesを使った動的イベント機能を追加します。デバッガのブレークポイントを設定するように、Linuxカーネル内の任意のアドレスに対して、新しいイベントを追加することが出来ます。また、レジスタやレジスタから参照されるメモリ内容の記録なども可能です。
この機能は*CONFIG_KPROBES*に依存しているのですが、一部のアーキテクチャ(armなど)ではデフォルトでこれが有効になっていないため、そのままでは設定項目が見えないことがあります。その場合、*"General Setup"*以下にある
*"Kprobes"*を選択してください。
使用していなければ特にオーバヘッドは無いため、有効にしておくことをおすすめします。

### Enable uprobes-based dynamic events (*CONFIG_UPROBE_EVENT*)

uprobesを使った動的イベント機能を追加します。これはptraceを使うよりも低いオーバヘッドで、ユーザ空間のアプリに対するイベントトレース機能を提供します。

### enable/disable function tracing dynamically (*CONFIG_DYNAMIC_FTRACE*)

これは前述のCONFIG_FUNCTION_TRACERを自己書き換え技術を利用して実装し、通常時のオーバヘッドを極端に減らすことができるオプションです。ある場合は必ず有効にしてください。（このオプションが残っているのはFtrace自体のデバッグのためです）

### Kernel function profiler (*CONFIG_FUNCTION_PROFILER*)

これは前述のCONFIG_FUNCTION_TRACERを使って、関数の実行回数に関する統計を取る仕組みです。頻繁に呼ばれる関数がどれかを調べることが可能です。
性能最適化において、一回の処理時間ではなく、呼び出し回数が多いためにボトルネックとなっている関数を見つけるのに有効です。
サンプリングベースのプロファイルでは見つけにくい症状が出た場合に利用することをおすすめします。

### Perform a startup test on ftrace (*CONFIG_FTRACE_STARTUP_TEST*)

カーネル起動時にFtraceの自己テストを実施します。起動時間が長くなるので、ftrace関係の開発を行ったり、新しいプラットフォーム上で動くかどうか不安な場合を除き、有効にしないほうが良いです。

#### Run selftest on syscall events (*CONFIG_EVENT_TRACE_TEST_SYSCALLS*)

起動時の自己テストに、全てのシステムコールのイベントのチェックを追加します。実行には非常に時間がかかるため、よほどの理由がない限り、有効にしないほうが良いです。

### Memory mapped IO tracing (*CONFIG_MMIOTRACE*)

全てのmemory mapped I/Oをトレースし、どのレジスタ（アドレス）にどういう値を書いたか、または読みだしたかを記録します。デバイスドライバのリバースエンジニアリングなどにお使いください。
（元々nvidiaドライバのREによりnouveauを作るために作られました）

### Histogram triggers (*CONFIG_HIST_TRIGGERS*)

カーネル内のイベントトレースにおいて、イベント情報のヒストグラムを作ることができる機能です。通常こうしたヒストグラムは、トレースデータの後処理を行うことで作成していましたが、この機能を有効にすると、その場で簡易なヒストグラムを得ることが出来ます。
性能解析や動作解析など、統計処理を簡易に行いたい場合などにおすすめです。

### Add tracepoint that benchmarks tracepoints (*CONFIG_TRACEPOINT_BENCHMARK*)

トレース機能自体の処理時間のベンチマークを取るための特殊なイベントを追加します。このイベントを実行すると、トレース機能がもたらす処理のオーバヘッドをマイクロベンチマークコードで測定します。Ftraceの開発者以外は必要ない機能ですが、もし新しいプラットフォーム上でオーバヘッドが気になるようなら、有効にして測ってみても良いでしょう。

### Ring buffer benchmark stress tester (*CONFIG_RING_BUFFER_BENCHMARK*)

トレース情報の記録に使うリングバッファの性能を計測するベンチマーク機能を追加します。（モジュール化可能）

### Ring buffer startup self test (*CONFIG_RING_BUFFER_STARTUP_TEST*)

起動時にリングバッファの動作を確認するストレステストを実施します。実行に10秒ほどかかります。リグレッションテスト用カーネル以外は無効にすることをおすすめします。

### Show enum mappings for trace events (*CONFIG_TRACE_ENUM_MAP_FILE*)

トレースしたイベントデータの引数を解釈する時に利用するenum(列挙型)の情報をenum_mapファイルとして見せる機能を追加します。
ユーザ空間でftraceを利用する高度なツールを作っているのでなければ、特に必要はないでしょう。

# オススメの設定
用途に応じて、以下の項目を設定することをおすすめします。

## デバッグ用(挙動解析含む)
関数とイベントのトレース、動的イベント追加、スナップショットがオススメ。
 - Kernel Function Tracer (*CONFIG_FUNCTION_TRACER*)
 - Kernel Function Graph Tracer (*CONFIG_FUNCTION_GRAPH_TRACER*)
 - Trace syscalls (*CONFIG_FTRACE_SYSCALLS*)
 - Create a snapshot trace buffer (*CONFIG_TRACER_SNAPSHOT*)
 - Enable kprobes-based dynamic events (*CONFIG_KPROBE_EVENT*)
 - Enable uprobes-based dynamic events (*CONFIG_UPROBE_EVENT*)
 - enable/disable function tracing dynamically (*CONFIG_DYNAMIC_FTRACE*)

## 性能解析用
デバッグ用のオプションに加えて、以下の項目を追加。
 - Interrupts-off Latency Tracer (*CONFIG_IRQSOFF_TRACER*)
 - Scheduling Latency Tracer (*CONFIG_SCHED_TRACER*)
 - Support for tracing block IO actions (*CONFIG_BLK_DEV_IO_TRACE*)
 - Kernel function profiler (*CONFIG_FUNCTION_PROFILER*)
 - Histogram triggers (*CONFIG_HIST_TRIGGERS*)
 - Add tracepoint that benchmarks tracepoints (*CONFIG_TRACEPOINT_BENCHMARK*)

## リグレッションテスト用
セルフテストとベンチマーク系を有効にする
 - Perform a startup test on ftrace (*CONFIG_FTRACE_STARTUP_TEST*)
 - Add tracepoint that benchmarks tracepoints (*CONFIG_TRACEPOINT_BENCHMARK*)
 - Ring buffer startup self test (*CONFIG_RING_BUFFER_STARTUP_TEST*)