TL

プロファイリングとパフォーマンス計測の原理

勘で速くしようとして外す前に。どこが遅いかを統計的に突き止めるサンプリングと計装の原理、PMUカウンタ、フレームグラフの読み方とマイクロベンチの罠を解き明かします。

応用プロファイリング性能計測PMUフレームグラフベンチマーク最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.サンプリング型は一定間隔でスタックを抜き取り、出現頻度から時間配分を統計推定する。計装型は計測コードを埋め込み正確だが観測自体が対象を歪める。
  • 2.CPUのPMU(性能監視ユニット)はキャッシュミスや分岐予測ミスをハードウェアで数え、命令数だけでは見えない停止要因を明らかにする。
  • 3.フレームグラフは横幅が総コスト、縦が呼び出し深さを表す。マイクロベンチはウォームアップ・DCE・測定オーバヘッドで容易に嘘をつく。

なぜ計測しなければ最適化できないのか

性能改善の鉄則は「推測するな、計測せよ」です。理由は単純で、プログラムの実行時間は人間の直感に反して偏るからです。多くのプログラムは全体の数パーセントのコードで実行時間の大半を消費します。アムダールの法則 が示すとおり、全体の5%しか占めない箇所をいくら速くしても、上限の改善は5%です。どこが遅いかを事実として突き止めることが、最適化の第一歩になります。

プロファイラはこの「どこ」を答える道具ですが、計測手法には統計的に推定するものと、正確に数えるものの二系統があり、それぞれ原理も誤差の性質も異なります。

サンプリング型プロファイラの統計的原理

サンプリング型は、一定間隔(例えば1ミリ秒ごと、毎秒1000回)でプログラムを割り込み、その瞬間のコールスタックを記録します。実行を止めて「今どこにいるか」を抜き取る方式です。各関数が記録された回数を数え、サンプル全体に占める比率を計算すると、その関数が消費した時間の比率の推定値が得られます。

原理の核心は、ある関数が時間 t の割合だけCPUを使っているなら、各サンプルがその関数を捉える確率も t になる、という点です。N 回のサンプルのうち捉えた回数 k から比率を t ≒ k/N と推定します。これは二項分布に従う統計的推定であり、誤差は標準偏差 sqrt(t(1-t)/N) に従って、サンプル数 N を増やすほど縮みます。つまりサンプリングは多数決であり、十分なサンプルがあれば真の配分に収束します。

なぜ稀な関数は信用できないのか

全体の0.1%しか占めない関数は、毎秒1000サンプルでも1秒あたり平均1回しか捉えられません。サンプル数が少ない関数の推定値は相対誤差が大きく、出現が0回か数回かは偶然に左右されます。フレームグラフの細い帯(少サンプルの関数)を見て「ここが問題」と判断してはいけないのは、統計的に根拠が薄いからです。太い帯ほど推定が信頼できます。

サンプリングの利点はオーバヘッドの低さです。割り込み頻度を固定すれば、計測コストは対象プログラムのサイズや関数呼び出し回数に依存せず一定に保てます。本番環境でも常時動かせる連続プロファイリングが成立するのはこのためです。欠点は、間隔より短い処理を取りこぼすことと、推定ゆえに小さな差を検出できないことです。

計装型プロファイラと観測者効果

計装型(instrumentation)は対象に直接計測コードを埋め込みます。各関数の入口と出口でタイムスタンプを取り、呼び出し回数と所要時間を正確に数える方式です。コンパイラが自動挿入する場合(gcc -pg など)も、手動で計測点を置く場合もあります。

正確さと引き換えに、計装は重大な代償を払います。計測コードそのものが実行時間を消費し、対象の挙動を変えてしまう——これが**観測者効果(プローブ効果)**です。とりわけ小さく頻繁に呼ばれる関数では、本体より計測コードの方が重くなりかねません。さらに深刻なのは、計装がコンパイラのインライン化を妨げる点です。計測点が関数境界を固定するため、本来インライン展開されて消えるはずの呼び出しが残り、実際とは違う性能像を示します。

観点サンプリング型計装型
計測原理周期割り込みで統計推定計測コード埋め込みで実数カウント
オーバヘッド低く一定(頻度依存)高く呼び出し回数に比例
正確さ確率的、稀な処理は誤差大回数は正確だが挙動を歪める
取りこぼし間隔より短い処理は漏れる原則すべて捕捉
本番常用可能通常は不可

CPUカウンタ(PMU)が見せる停止の理由

実行時間を「どの関数で使ったか」まで分かっても、なぜその関数が遅いのかは分かりません。同じ命令数でも、キャッシュからデータが届かず待たされていれば何倍も遅くなります。ここで使うのが、現代CPUに内蔵された**PMU(Performance Monitoring Unit、性能監視ユニット)**です。

PMUはハードウェアレベルのイベントカウンタで、実行サイクル数・退役命令数のほか、キャッシュ ミス、分岐予測ミス、TLBミスといったマイクロアーキテクチャ上の事象を直接数えます。これらはソフトウェアからは観測できず、ハードウェアの支援が不可欠です。

最も基本的な指標が IPC(命令/サイクル)、またはその逆数の CPI です。理想的なスーパースカラCPUは1サイクルに複数命令を退役できますが、IPCが低い(例えば0.5を切る)なら、CPUは命令を実行できず**ストール(停止)**しています。その原因をPMUのイベント比で切り分けます。

低IPCの切り分け(イベント比から原因を推定)
  キャッシュミス率が高い   → メモリ待ち(データ局所性の問題)
  分岐予測ミス率が高い     → 制御フローが予測不能(パイプライン破棄)
  退役命令数が異様に多い   → アルゴリズム/命令数そのものの問題
PMUサンプリングという合わせ技

PMUは「カウンタが一定値に達したら割り込む」設定ができます。これを使い「キャッシュミスがN回起きるごとにスタックを記録」すると、ミスを多発させているコード上の位置が分かります。サンプリングの統計手法とPMUのハードウェア計測を組み合わせた方式で、Linux の perf はこれを標準で行います。命令数では見えない「どの行でメモリを待っているか」を可視化できます。

フレームグラフの読み方

サンプリングで集めた大量のスタックを可視化する標準的な手段がフレームグラフです。読み方を誤ると結論を間違えるため、軸の意味を正確に押さえます。

  • 横幅 = 総コスト。ある関数のボックスの横幅は、その関数(と配下の呼び出し全体)が出現したサンプル比率です。幅の広いものが重い。横軸は時間軸ではなく、アルファベット順などに整列された集約であり、左右の位置に時間的意味はありません。
  • 縦 = 呼び出しの深さ。下が呼び出し元、上が呼び出し先です。最上部の平らな部分(葉)が、実際にCPUを使っていた地点を表します。
  • 自己時間 vs 総時間。あるボックスの幅は配下を含む総時間です。配下のボックスがその幅を埋め尽くしていれば、その関数自身はほとんど時間を使わず子に委ねているだけ。逆に上に何も乗っていない平らな天面の幅が、その関数の自己時間です。

最適化対象を探すコツは、幅の広い平らな天面を見つけることです。それは「多くの時間を、自分自身で消費している」関数であり、改善余地が大きい候補です。広い帯でも上が細かく分岐していれば、ボトルネックはさらに下層に分散しています。

マイクロベンチマークの落とし穴

特定の関数だけを繰り返し計測するマイクロベンチマークは、原理を理解せずに書くと容易に嘘の数字を出します。代表的な罠を挙げます。

マイクロベンチが嘘をつく主な理由

ウォームアップ不足: JIT 言語は実行を重ねて初めて最適化され、CPUのキャッシュや分岐予測器も温まる。初回計測は本来の性能を表さない。
デッドコード除去(DCE): 計算結果を使わないと、コンパイラが処理ごと削除し「0ナノ秒」になる。結果を消費させる工夫(ブラックホール)が要る。
定数畳み込み: 入力がコンパイル時定数だと、ループ全体が事前計算され実行時の仕事が消える。
測定オーバヘッド: 計測する時刻取得そのものが、計測対象より重いことがある。1回でなくループ全体を計測し1回あたりに割る。

これらに加え、計測値は分布として扱う必要があります。GCの一時停止、OSのスケジューリング、他プロセスとの干渉により、実行時間は揺らぎます。1回の値や単純平均は外れ値に引きずられるため、中央値や分位点(p99など)で評価し、複数回の試行でばらつき自体を見ます。「Aの方が速い」と言うには、その差が計算量 の差なのか、測定誤差の範囲なのかを区別しなければなりません。前者ならスケールに応じて広がり、後者なら試行を増やせば消えます。

まとめ

プロファイリングは、当てずっぽうの最適化を排し、事実として遅い場所を特定する手段です。サンプリング型は周期割り込みで時間配分を統計推定し、低オーバヘッドゆえ本番でも使えますが、稀な処理は誤差が大きい。計装型は正確に数える代わりに観測者効果で対象を歪めます。「なぜ遅いか」はPMUのハードウェアカウンタが答え、IPCとイベント比からメモリ待ちや分岐予測ミスを切り分けます。フレームグラフは幅が総コスト・縦が深さであり、広い平らな天面が改善候補です。そしてマイクロベンチはウォームアップ・DCE・測定オーバヘッドという罠に満ち、計測値は分布として扱って初めて信頼できます。

プログラミング Article

プロファイリングとパフォーマンス計測の原理を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

プロファイリング

比較で見る軸

難易度: advanced / カテゴリ: プログラミング / タグ数: 5

導入後に効く点

CPUのPMU(性能監視ユニット)はキャッシュミスや分岐予測ミスをハードウェアで数え、命令数だけでは見えない停止要因を明らかにする。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
プログラミング
タグ数
5

判断チェックリスト

  • 自社の用途が「プロファイリング / 性能計測」に近いか確認する。
  • 強みである「サンプリング型は一定間隔でスタックを抜き取り、出現頻度から時間配分を統計推定する。計装型は計測コードを埋め込み正確だが観測自体が対象を歪める。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

プロファイリング性能計測PMUフレームグラフベンチマークプロファイリング性能計測PMU