性能解析(パフォーマンス解析)とは、プログラムの実行を通して情報を収集し、その性能を分析する動的プログラム解析の一種です。プログラムを実行せずに解析する静的コード解析とは対照的です。性能解析の主な目的は、プログラムの実行時間やメモリ使用量を最適化するために、どの部分を改良すべきかを特定することです。これは、
ボトルネックを特定し、
アムダールの法則を考慮した改善策を見つける上で重要になります。
プロファイラの利用
性能解析において中心的な役割を果たすのがプロファイラです。プロファイラは、プログラム実行時の関数呼び出し頻度や実行時間などの情報を収集します。収集されたデータは、イベントの羅列(トレース)または統計的要約(プロファイル)として出力されます。プロファイラのデータ収集方法は多岐にわたり、ハードウェア割り込み、コードへの命令埋め込み、
オペレーティングシステムフック、性能カウンタなどが利用されます。プロファイラはパフォーマンスエンジニアリングにおいて不可欠なツールです。
プロファイルは、ソースコードの位置と関連付けてイベントを統計的に記録するため、データサイズはコードサイズに比例します。一方、トレースのサイズはプログラムの実行時間に比例するため、実用的でない場合もあります。並列性のないプログラムではプロファイルで十分なことが多いですが、並列性のあるプログラムでは、イベントの
時系列順序が重要になるため、完全なトレースが必要になることがあります。
歴史
UNIXにおけるプロファイラを用いた性能解析は、1979年の"prof"ツールの登場に遡ります。"prof"は関数毎の実行時間をリストアップするツールでした。1982年には"gprof"が登場し、コールグラフによる詳細な解析が可能になりました。
1994年、Amitabh Srivastava と Alan Eustace は、プログラムをプロファイラに変換するシステムであるATOMに関する論文を発表しました。ATOMは、コンパイル時に解析用の命令を挿入し、実行時にその命令によって解析データを出力します。この手法は"instrumentation"(計測化)と呼ばれます。
2004年には、GprofとATOMの論文が、ACM SIGPLANの学会誌Programming Language Design and Implementationに掲載された最も影響力のある20本に選ばれました。
出力による分類
プロファイラは、出力される情報に基づいて以下の種類に分類できます。
フラット・プロファイラ: ルーチン毎の平均実行時間を計算しますが、呼び出し側のコンテキストは考慮しません。
コールグラフ・プロファイラ: 呼び出し回数や頻度を表示し、呼び出し関係を辿った解析が可能ですが、コンテキスト(引数など)は考慮しません。
データ収集法
プロファイラは、データ収集方法によってさらに分類できます。
イベントベースのプロファイラ: 特定のイベント(メソッド呼び出し、クラスのロード/アンロードなど)を捕捉します。
.NET Framework、
Java、
JavaScript、
Python、
Rubyなどがこの手法をサポートしています。
統計的プロファイラ: プログラムカウンタを一定間隔でサンプリングし、統計的な情報を収集します。精度は低いものの、プログラムの実行速度への影響が少ないという利点があります。サンプリング間隔を短くすれば誤差は小さくなります。
手段
性能解析を行う手段は様々です。
マニュアル(手動): プログラマが実行時間を計算するコードを明示的に組み込みます。
コンパイラ補助: コンパイル時にプロファイラ用のコードを組み込みます(例: `gcc -pg ...`)。
バイナリ変換: コンパイル済みのバイナリに命令を追加します(例: ATOM)。
ランタイム補助: ツールの監視下でプログラムを実行します(例: PIN, Valgrind)。
ランタイム挿入: 実行時にコードを修正し、ヘルパー関数へジャンプするようにします(例: DynInst)。
ハイパーバイザ: ハイパーバイザ上でプログラムを実行し、ハイパーバイザが情報を収集します(例: SIMMON)。
シミュレータ: 命令セットシミュレータ上でプログラムを実行し、情報を収集します(例: SIMMON)。
実際の性能解析と性能強化
性能解析は、プログラムの
バグを修正するだけでなく、性能を向上させるための重要なステップです。プログラムの実行時間が長い場合、
デバッガを使用してコールスタックを調査することで、問題のある箇所を特定できます。無限ループの場合、一時停止させ、コールスタックの変化を追うことで特定できます。ループの実行時間が長い場合も同様に、
デバッガとコールスタック調査を活用できます。
性能強化は、プログラムの誤動作は引き起こさないものの、実行時間を遅くする
バグ(スラグ)の修正です。スラグにはさまざまな種類があり、実行時間のほとんどを占める「ホットスポット」や、
データ構造が適切でないために性能が低下する場合などがあります。性能解析では、統計的プロファイラの精度よりも、スタックトレースなどの情報の方が重要になります。
主なプロファイラ
以下に、主なプロファイラをいくつか紹介します。
多言語対応: Performance Application Programming Interface (PAPI), gprof, Valgrind, PerfSuite, OProfile, CodeAnalyst, Sysprof, DynaProf, TAU, DynInst, Oracle Solaris Studio Performance Analyzer, Intel VTune Amplifier XE, Windows Performance Toolkit, shinyprofiler, Simpleperf.
Java:
Java VisualVM, Test and Performance Tools Platform Project (TPTP),
NetBeans Debugger and Profiler, JProfiler, JRat, YourKit
Java Profiler.
.NET Framework: Visual Studio プロファイリング ツール, CLR Profiler, NProf.
Delphi: Pro
Delphi, GpProfile.
Perl: Devel::DProf, Devel::Profiler.
ActionScript: Flex Builder プロファイラ,
IntelliJ IDEA Flash/Flex Profiler plugin.
JavaScript: Firebug, Google Chrome Developer Tools, Safari Developer Tools, Nodetime.
これらのプロファイラは、プログラムの性能問題を解決するために重要な役割を果たします。適切なツールを選択し、効果的な解析を行うことで、プログラムのパフォーマンスを大幅に向上させることが可能です。
関連項目
パフォーマンスエンジニアリング
性能予測
最悪実行時間
参照
Gprof: a Call Graph Execution Profiler
ATOM
20 Most Influential Papers
外部リンク
Using VSTS Performance Tools to Speed Up Your App