コールグラフ

コールグラフ (マルチグラフとも呼ばれる) とは、コンピュータプログラムのサブルーチン同士の呼び出し関係を表現した有向グラフである。具体的には、各ノードが手続きを表現し、各エッジ(f,g)は手続きfが手続きgを呼び出すことを示す。従って、循環したグラフは再帰的な関数呼び出しを示す。 コールグラフはプログラムの初歩的な解析の結果であり、プログラムを人間が可読なものにするため、あるいはたとえば手続き間の変数の追跡を行う解析といった発展的な解析のための基礎として用いることができる。コールグラフの簡単な利用方法は、一度も呼び出されない関数を見つけることである。 コールグラフは 動的でも静的でもありうる。動的なコールグラフはプログラムの実行結果の記録、たとえばプロファイラの出力である。従って、動的なコールグラフは正確であるが、プログラムの一度の実行結果を記述できるのみである。正確な静的コールグラフは非決定論的であり、静的なコールグラフ抽出の アルゴリズムは一般的に過剰な見積もりに基づいている。つまり、実際に生じる各呼び出し関係もグラフ内に表現されるが、プログラムの実際の動作では一度も生じないいくつかの呼び出し関係も表現される。 コールグラフは正確さによって異なる形で表現することができる。より正確なコールグラフは長い計算時間と大きなメモリ消費量を代償として、たとえばプロファイラの出力結果などの形式により、実際のプログラムの振る舞いより正確に見積もることができるよう表現することができる。最も正確なコールグラフは「コンテキストを理解した」コールグラフ、すなわち各手続きについて手続きが呼び出されるコールスタックごとに別々のノードを持つようにしたものである。完全に「コンテキストを理解した」コールグラフは生成に膨大なメモリを消費するが計算は簡単に行うことができる。大規模なプログラムでは計算時間がかかりすぎるため、完全に「コンテキストを理解した」コールグラフを静的に求めることはできない。最も正確さが低いコールグラフは「コンテキストを理解しない」ものであり、各手続きについてノードを一つしか持たない。 動的なディスパッチを備えるJavaやC++などの言語では、静的なコールグラフを正確に求めるためにはエイリアス解析の結果を必要とする。逆に言えば、正確なエイリアスを求めるためにはコールグラフが必要である。静的な解析システムは二つを同時に求めることで、この相互に相手を必要とする問題(無限後退)を解決する。 コールグラフという用語はコンパイラやバイナリ変換のコミュニティでよく用いられる。 codeviz 静的なコールグラフ生成プログラム（対象プログラムは実行しない）。gccに対するパッチとして実装されており、Cおよび C++に対応している。 egypt 短いPerlスクリプトで、gccとGraphvizを用いてCプログラムの静的なコールグラフを生成する。 gprof GNU Binutilsの一部である。 pycallgraph Graphvizを用いてPythonプログラムのコールグラフを生成する。 doxygen Graphvizを用いて静的な呼び出し、継承の図を生成する。 aiCall 無料の評価版が存在する。 Graphviz テキストにより表現されたグラフ（コールグラフを含む）を図に変換する。GProfとともに用いる必要がある。UNIX哲学に基づき、gprof単体では図の描画を行わない。 例として、GProfが自分自身を解析した結果のコールグラフを示す。 index called name |index called name 72384/72384 sym_id_parse [54] | 1508/1508 cg_dfn [15] [3] 72384 match [3] |[13] 1508 pre_visit [13] ---------------------- |---------------------- 4/9052 cg_tally [32] | 1508/1508 cg_assemble [38] 3016/9052 hist_print [49] |[14] 1508 propagate_time [14] 6032/9052 propagate_flags [52] |---------------------- [4] 9052 sym_lookup [4] | 2 cg_dfn [15] ---------------------- | 1507/1507 cg_assemble [38] 5766/5766 core_create_function_syms [41]|[15] 1507+2 cg_dfn [15] [5] 5766 core_sym_class [5] | 1509/1509 is_numbered [9] ---------------------- | 1508/1508 is_busy [11] 24/1537 parse_spec [19] | 1508/1508 pre_visit [13] 1513/1537 core_create_function_syms [41]| 1508/1508 post_visit [12] [6] 1537 sym_init [6] | 2 cg_dfn [15] ---------------------- |---------------------- 1511/1511 core_create_function_syms [41]| 1505/1505 hist_print [49] [7] 1511 get_src_info [7] |[16] 1505 print_line [16] ---------------------- | 2/9 print_name_only [25] 2/1510 arc_add [31] |---------------------- 1508/1510 cg_assemble [38] | 1430/1430 core_create_function_syms [41] [8] 1510 arc_lookup [8] |[17] 1430 source_file_lookup_path [17] ---------------------- |---------------------- 1509/1509 cg_dfn [15] | 24/24 sym_id_parse [54] [9] 1509 is_numbered [9] |[18] 24 parse_id [18] ---------------------- | 24/24 parse_spec [19] 1508/1508 propagate_flags [52] |---------------------- [10] 1508 inherit_flags [10] | 24/24 parse_id [18] ---------------------- |[19] 24 parse_spec [19] 1508/1508 cg_dfn [15] | 24/1537 sym_init [6] [11] 1508 is_busy [11] |---------------------- ---------------------- | 24/24 main [1210] 1508/1508 cg_dfn [15] |[20] 24 sym_id_add [20] [12] 1508 post_visit [12] |