フレームグラフを読むのは簡単ではありません。練習が必要です。ですが、ちょっとしたコツもあります。ここではそれを紹介します。
フレームグラフやウォーターフォールチャートを呼ばれる種類の可視化を見ないで1日を過ごすことは、ほとんどありません。大抵はSpeedscopeやChrome DevToolsで、そういった可視化を目にしています。
著書の多くやワークショップの中でフレームグラフの読み方を教えていると、そこでつまづく人を見かけます。フレームグラフを読んで理解するのは、ある程度はスキルの話です。スキルを身につけるには、絶え間ない練習が必要です。
ただ、フレームグラフを読むスキルはサブスキルに分解できます。その場合に最も重要だと私が考えるのは、「どのフレームが重要で意味があるのかを判断できる」スキルです。
プロセスは、Xミリ秒ごとに停止します。停止されると、プロセスの現在のスタックが記録されます。例えば、フレームAはフレームBを呼び、フレームBはフレームCを呼び出すといった具合です。念のために言っておくと、実行スタックとは、例外のバックトレースを見るときなどに表示されているもののことです。例外はスタックを一度だけキャプチャしますが、パフォーマンスプロファイラはミリ秒単位の一定間隔でスタックをキャプチャします。
フレームグラフは、そうやって記録されたスタックを並べることで、このプロセスを視覚化したものです。その視覚化の結果が「炎」のように見えることから、「フレームグラフ」と呼ばれるようになりました。この可視化を、すべてのスタックフレームの「親」が下ではなく上になるように行うと、滝のように見えるので「ウォーターフォールチャート」になります。どちらも同じことなんですけどね。SpeedscopeやDevToolsはウォーターフォール形式でこれを可視化するのですが、私は気にせずにフレームグラフと呼んでいます。
フレームグラフを効果的に読むのに必要なのは、どのフレームを無視すればいいかを理解することです。どのスタックにも、私が「パススルー」と呼ぶフレーム、つまり基本的に何もしないフレームが存在します。パススルーフレームは簡単に見分けられます。
- ... パススルーフレームは、フレーム内で実際に費やされる時間が非常に短いです。そうしたフレームは、決してスタックの最上位にはなく、子フレームを呼び出すことだけをしています。これは通常、そのフレームが大したことを行っていないのを示す良い指標です。
- ... パススルーフレームは、ルートフレームの近く、フレームグラフのベース部分にあります。スタックの「上」に行けば行くほど、アプリケーションコードに近くなり、読む価値のあるフレームとなります。
- ... パススルーフレームは、依存関係の中にあります。フレームのソースコードの位置を見て見ましょう。それは、ライブラリの内部を指しているでしょうか。それともアプリケーション内を指しているでしょうか? アプリケーションディレクトリにあるほとんどすべて* のフレームは重要です。ですが、しばしば依存関係が姿を表し、面白くないフレームをたくさん追加します。
逆に、どのフレームが興味深いかを知っておくのも大切です。
興味深いフレームとは、ソースコードの位置がアプリケーションのルートディレクトリにあるフレームです。フレームグラフツールは、異なるソースコードディレクトリを異なる色で視覚化するのが一般的です。どの色が「アプリケーションのディレクトリ内」を意味するのかを素早く探し、他のほとんどの色は無視して見始めるのが良いでしょう。
子フレームを呼び出していない、「自己完結」している時間が長いフレーム。これは、スタックのさらに上のフレームがないことを意味します。
そうしたフレームこそ、私がフレームグラフを見る際に最も時間を費やす場所です。
フレームグラフのキャプチャは、最近は非常に簡単で、何をプロファイリングしようとしているかに依存します。
- rack-mini-profilerは、Railsのバックエンドリクエストのフレームグラフを生成してくれます。
- Chrome DevToolsは、ブラウザの動作やページのロードについて、パフォーマンスタブで優れたフレームグラフを生成します。
- stackprofは単体で任意のRubyコードのフレームグラフを生成できます。
- TestProfは、Rubyのテストスイートのフレームグラフを取得するために使えます。
フレームグラフはパフォーマンス向上のための重要なツールです。ですが、最初にそれを理解できなくても、気にしないでください。みんなも同じです。試し続け、見続けていけば、最終的には効果的に使用するのに必要な「パターン認識」を学べるはずです。
それでは、また来週。