はじめに
- Rust のコードをプロファイリングして FlameGraph を描画する手順をまとめる。
- FlameGraph は横軸を CPU 実行時間、縦軸をコールスタックとするグラフで、関数同士の呼び出し関係や CPU 実行時間が視覚的にわかりやすく表現されるため、パフォーマンスチューニングなどに役に立つ。
プロファイリング可能なバイナリを用意する
プロファイリングできるように設定する
- Cargo.toml を変更してプロファイリングができるようにする
Cargo.toml
[profile.release]
debug = true
ビルドする
- リリースバージョンでビルドする
cargo build --release
DTrace でプロファイリングする
- 以下の通りにビルドしたバイナリを実行し DTrace でプロファイリングをする
sudo dtrace -c './target/release/your_binary' -o out.stacks -n 'profile-997 /pid == $target/ { @[ustack(100)] = count(); }'
各オプションの解説
-
-c
に実行コマンドを指定する。- 例はビルドしたバイナリファイル名が
./target/release/your_binary
である場合。引数などがあればこれに追記する。
- 例はビルドしたバイナリファイル名が
-
-o
にプロファイリング結果を記録するファイル名を指定する -
-n
にプロファイリング処理内容を記載する。- プロファイリング処理内容は dtrace のドメイン特化言語 D 言語で記載される。
D 言語の解説
- D 言語の主な文法は
プローブ / 述語 / { アクション }
というものである。 -
プローブ
はプロファイリングを行うポイントを指定する部分。- 例のように
profile-997
と指定すると 997 ヘルツごとにプロファイリングの処理が差し込まれる。
- 例のように
-
述語
はプロファイリングのアクションを実行するかどうかを判定する部分。- 例のように
pid == $target
とすると PID が $target の場合にアクションを実行する。 -
$target
は-c
オプションで実行されたコマンドの PID が入っている変数。
- 例のように
-
アクション
はプロファイリングの処理。-
@[]
は集計関数 -
ustack(100)
はユーザーのコールスタック 100 フレーム分を返す関数 -
count()
は呼び出された回数を返す関数 - 全部合わせると
ユーザーのコールスタックにある関数が呼び出された回数を数え上げる
という内容になる。
-
FlameGraph を描画する
- FlameGraph を描画するプログラムをダウンロードする
git clone https://github.com/brendangregg/FlameGraph
- プロファイリング結果のファイルを使って FlameGraph の SVG ファイルを描画する
FlameGraph/stackcollapse.pl out.stacks | FlameGraph/flamegraph.pl > graph.svg
- 表示する
open graph.svg