(57)【特許請求の範囲】
【請求項１】
コンピュータが、
関数が実行される際に、該関数の呼び出し情報を収集し、
収集した呼び出し情報を非可逆圧縮するか否かを選択し、
非可逆圧縮を選択した場合には、前記呼び出し情報を非可逆圧縮してサンプリングデータとして記憶部に格納し、非可逆圧縮を選択しなかった場合には、前記呼び出し情報を圧縮することなく、又は、可逆圧縮して前記記憶部にサンプリングデータとして格納し、
前記記憶部に格納したサンプリングデータを読み出し、該読み出したサンプリングデータに含まれる圧縮されなかった呼び出し情報又は可逆圧縮された呼び出し情報を用いて、非可逆圧縮された呼び出し情報と、圧縮されなかった呼び出し情報又は可逆圧縮された呼び出し情報とを対応付けた逆圧縮表を作成し、
非可逆圧縮された呼び出し情報から元の呼び出し情報を前記逆圧縮表に基づいて復元し、
圧縮されなかった呼び出し情報又は可逆圧縮された呼び出し情報と復元された呼び出し情報に基づいて関数の呼び出し関係を集計する
処理を実行することを特徴とする関数呼び出し情報収集方法。
【請求項２】
コンピュータに、
関数が実行される際に、該関数の呼び出し情報を収集し、
収集した呼び出し情報を非可逆圧縮するか否かを選択し、
非可逆圧縮を選択した場合には、前記呼び出し情報を非可逆圧縮してサンプリングデータとして記憶部に格納し、非可逆圧縮を選択しなかった場合には、前記呼び出し情報を圧縮することなく、又は、可逆圧縮して前記記憶部にサンプリングデータとして格納し、
前記記憶部に格納したサンプリングデータを読み出し、該読み出したサンプリングデータに含まれる圧縮されなかった呼び出し情報又は可逆圧縮された呼び出し情報を用いて、非可逆圧縮された呼び出し情報と、圧縮されなかった呼び出し情報又は可逆圧縮された呼び出し情報とを対応付けた逆圧縮表を作成し、
非可逆圧縮された呼び出し情報から元の呼び出し情報を前記逆圧縮表に基づいて復元し、
圧縮されなかった呼び出し情報又は可逆圧縮された呼び出し情報と復元された呼び出し情報に基づいて関数の呼び出し関係を集計する
処理を実行させることを特徴とする関数呼び出し情報収集プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、関数呼び出し情報収集方法及び関数呼び出し情報収集プログラムに関する。
【背景技術】
【０００２】
プログラムの実行性能を高めたり、性能特性を分析することを目的として、プログラムの性能プロファイルを採取することが行われる。性能プロファイルには、例えば、プログラム実行中に処理された関数の実行頻度がある。実行頻度の高い関数の性能を向上させることで、プログラム全体の性能を向上させることができる。
【０００３】
実行頻度を求める方法の１つとして、一定時間毎にＣＰＵの命令カウンタの値すなわち実行番地をサンプリングしてメモリ等に保存し、プログラムの実行終了後に保存した番地に対応する関数を決定することで関数毎の出現回数を実行回数として算出する方法がある。出現回数は、一定時間毎にサンプリングされたタイミングで実行されている関数の回数であり、実際に関数が実行された回数とは異なる。ただし、繰り返し実行される関数は実行時間が長くなり、繰り返し実行される関数の出現回数は多くなる。
【０００４】
関数の実行頻度は、関数の呼び出し関係に基づいて分析されることが多い。例えば、関数Ｃの実行回数を１００回とするとき、８０回は関数Ａ→関数Ｂ→関数Ｃの順で呼ばれた場合であり、残りの２０回は関数Ｘ→関数Ｙ→関数Ｚ→関数Ｃの順で呼ばれた場合であるといった分析が行われる。
【０００５】
なお、メソッドを一例とするプロファイル情報取得対象を指定し、指定されたプロファイル情報取得対象が実行中か否かを一定時間間隔で監視し、実行中であるときにプロファイル情報を取得することで、取得のためのオーバヘッドを小さくする従来技術がある。
【０００６】
また、ソースプログラム中の関数呼び出しを検出してコールペアの種別毎に識別番号を付し、識別番号毎に関数呼び出しの回数を格納するテーブル領域を設定することで、プロファイル処理時のメモリ領域とオーバヘッドを削減する従来技術がある。
【０００７】
また、ソースプログラムに、動的呼び出し側関数と動的呼び出され側関数の組み合わせである動的コールペア毎に呼び出し回数を格納するテーブルの領域を設定する処理を挿入することで、コールペア情報を収集する際の計算量とメモリ量を削減する従来技術がある。
【先行技術文献】
【特許文献】
【０００８】
【特許文献１】特開２００５−１４１３９２号公報
【特許文献２】特開平１１−２１２８３７号公報
【特許文献３】特開２００６−２０２１３４号公報
【発明の概要】
【発明が解決しようとする課題】
【０００９】
関数の呼び出し関係に基づいて関数の実行頻度を分析する場合、関数呼び出し関係の情報もメモリに格納する必要があり、メモリに格納されるプロファイル情報が多くなるという問題がある。メモリに格納されるプロファイル情報が多くなると、プロファイル情報の採取対象であるプログラムの実行性能に影響を与える場合もある。
【００１０】
本発明は、１つの側面では、関数呼び出し関係の情報のメモリ上の量を削減することを目的とする。
【課題を解決するための手段】
【００１１】
本願の開示する関数呼び出し情報収集方法は、１つの態様において、関数が実行される際に、該関数の呼び出し情報を収集し、収集した呼び出し情報を非可逆圧縮するか否かを選択する処理をコンピュータが実行する。そして、非可逆圧縮を選択した場合には、前記呼び出し情報を非可逆圧縮してサンプリングデータとして記憶部に格納し、非可逆圧縮を選択しなかった場合には、前記呼び出し情報を圧縮することなく、又は、可逆圧縮して前記記憶部にサンプリングデータとして格納し、前記記憶部に格納したサンプリングデータを読み出し、該読み出したサンプリングデータに含まれる圧縮されなかった呼び出し情報又は可逆圧縮された呼び出し情報を用いて、非可逆圧縮された呼び出し情報と、圧縮されなかった呼び出し情報又は可逆圧縮された呼び出し情報とを対応付けた逆圧縮表を作成し、非可逆圧縮された呼び出し情報から元の呼び出し情報を前記逆圧縮表に基づいて復元し、圧縮されなかった呼び出し情報又は可逆圧縮された呼び出し情報と復元された呼び出し情報に基づいて関数の呼び出し関係を集計する処理をコンピュータが実行する。
【発明の効果】
【００１２】
１実施態様によれば、関数呼び出し関係の情報のメモリ上の量を削減することができる。
【図面の簡単な説明】
【００１３】
【図１】図１は、実施例に係る性能情報収集プログラムを説明するための図である。
【図２】図２は、性能収集用割込みプログラムの動作を説明するための図である。
【図３】図３は、性能収集対象のプログラムの動作を説明するための図である。
【図４】図４は、関数呼び出し時にスタックに積まれるデータを説明するための図である。
【図５Ａ】図５Ａは、関数の呼び出し時に実行されるコードの一例を示す図である。
【図５Ｂ】図５Ｂは、関数の戻り時に実行されるコードの一例を示す図である。
【図６】図６は、サンプリングデータの形式を示す図である。
【図７】図７は、unwind_stackプログラムの処理のフローを示すフローチャートである。
【図８】図８は、分析プログラムの機能構成を示す図である。
【図９Ａ】図９Ａは、分析プログラムの第１のパスを説明するための図である。
【図９Ｂ】図９Ｂは、分析プログラムの第２のパスを説明するための図である。
【図１０Ａ】図１０Ａは、第１のパスの処理のフローを示すフローチャートである。
【図１０Ｂ】図１０Ｂは、第２のパスの処理のフローを示すフローチャートである
【図１１Ａ】図１１Ａは、サンプリング結果の集計処理の第１の例を示すフローチャートである。
【図１１Ｂ】図１１Ｂは、サンプリング結果の集計処理の第２の例を示すフローチャートである。
【図１２】図１２は、トライ木の一例を示す図である。
【図１３】図１３は、性能情報収集プログラムを実行するコンピュータの構成を示す図である。
【発明を実施するための形態】
【００１４】
以下に、本願の開示する関数呼び出し情報収集方法及び関数呼び出し情報収集プログラムの実施例を図面に基づいて詳細に説明する。なお、この実施例は開示の技術を限定するものではない。
【実施例】
【００１５】
まず、実施例に係る性能情報収集プログラムについて説明する。図１は、実施例に係る性能情報収集プログラムを説明するための図である。図１に示すように、性能情報収集プログラム１は、サンプリングプログラム２と、分析プログラム４とを有する。
【００１６】
サンプリングプログラム２は、関数呼び出し関係の情報をサンプリングするためのプログラムであり、サンプリングした関数呼び出し関係の情報をサンプリングデータとしてサンプリングデータ記憶部３に格納する。サンプリングプログラム２は、unwind_stackプログラム２１と、性能収集用割込みプログラム２２を有する。
【００１７】
unwind_stackプログラム２１は、スタックから関数呼び出し関係の情報を取得してサンプリングデータとしてレジスタに格納する。unwind_stackプログラム２１は、性能収集が行われるプログラムである性能収集対象プログラムの各関数の実行開始時に実行される。
【００１８】
性能収集用割込みプログラム２２は、一定時間間隔で起動され、unwind_stackプログラム２１がレジスタに格納したサンプリングデータをメモリに格納する。メモリに格納されたサンプリングデータは、性能情報の収集が終了した時点等にサンプリングデータ記憶部３に書き出される。
【００１９】
なお、unwind_stackプログラム２１が関数呼び出し関係の情報を取得するタイミングは各関数の実行開始時であり、性能収集用割込みプログラム２２が関数呼び出し関係の情報をメモリに格納するタイミングは一定時間間隔である。すなわち、両者は異なる。
【００２０】
分析プログラム４は、サンプリングデータ記憶部３から関数呼び出し関係の情報を読み出して関数の呼び出し関係に基づく関数の出現回数を集計し、集計結果を集計結果記憶部５に格納する。
【００２１】
次に、性能収集用割込みプログラム２２の動作について説明する。図２は、性能収集用割込みプログラム２２の動作を説明するための図である。図２では、メモリ６１のヒープ６１ｂに格納された性能収集対象コード７１が実行されているとする。ここで、性能収集対象コード７１は、性能収集対象プログラムの実行コードである。性能収集対象コード７１には、unwind_stackプログラム２１の実行コードであるunwind_stackコード７１ａが含まれる。
【００２２】
ヒープ６１ｂは、動的に確保可能なメモリ領域であり、プログラムの実行コードやデータ等が格納される領域である。ヒープ６１ｂには、性能収集対象コード７１以外にハッシュ関数コード７２、性能収集用割込みコード７３、サンプリングバッファ７４が含まれる。ハッシュ関数コード７２は、ハッシュ値を計算するハッシュ関数の実行コードである。性能収集用割込みコード７３は、性能収集用割込みプログラム２２の実行コードである。サンプリングバッファ７４は、性能収集用割込みプログラム２２により収集されたサンプリングデータを格納する領域である。
【００２３】
図２に示すように、ＣＰＵ６２の性能を監視するＰＭＵ（Performance  Monitoring  Units）６２ａがＣＰＵ６２に対して性能収集用割込みを定期的に発生する（１）。なお、ＰＭＵ６２ａの代わりにクロックカウンタ、タイマ等がＣＰＵ６２に対して性能収集用割込みを定期的に発生してもよい。
【００２４】
そして、ＣＰＵ６２は、割込み処理を実行する（２）。具体的には、ＣＰＵ６２は、命令ポインタ８１の値を性能収集用割込みコード７３の先頭とし、性能収集用割込みコード７３を実行する。ここで、命令ポインタ８１は、実行するコードのアドレスを記憶するレジスタであり、ＣＰＵ６２のレジスタセット８０に含まれる。
【００２５】
性能収集用割込みコード７３は、ｍ（ｍは正の整数）個の呼び出し関係格納専用レジスタ８５から関数呼び出し関係の情報を読み出してサンプリングバッファ７４にサンプリングデータとして書き込む（３）。ここで、呼び出し関係格納専用レジスタ８５は、レジスタセット８０に含まれる汎用レジスタ８４の一部である。unwind_stackプログラム２１により関数呼び出し関係の情報がｍ個の呼び出し関係格納専用レジスタ８５に格納される。
【００２６】
その後、性能情報収集時間が終了すると、性能収集用割込みプログラム２２によるデータ収集が終了し（４）、サンプリングプログラム２は、サンプリングデータの永続化、すなわち、サンプリングデータのサンプリングデータ記憶部３への書き込みを行う（５）。なお、サンプリングデータのサンプリングデータ記憶部３への書き込みは、サンプリングバッファ７４に空きがなくなったときにも行われる。
【００２７】
このように、性能収集用割込みプログラム２２は、一定時間間隔で起動され、起動された時点で呼び出し関係格納専用レジスタ８５が記憶する関数呼び出し関係の情報をサンプリングバッファ７４に格納することで、関数呼び出し関係の情報を収集することができる。
【００２８】
次に、unwind_stackプログラム２１の動作について図３〜図７を用いて説明する。まず、性能収集対象プログラムの動作について説明する。図３は、性能収集対象のプログラムの動作を説明するための図である。
【００２９】
図３に示すように、性能収集対象コード７１の実行が開始され（１）、命令ポインタ８１が指すアドレスの命令が順番に実行される。そして、実行の途中で関数の呼び出しが行われる（２）と、命令ポインタ８１が記憶する戻り命令アドレスがスタック６１ａにｐｕｓｈされる（３）。ここで、スタック６１ａは、メモリ６１内でデータをＦＩＬＯ（First  In  Last  Out）で格納する領域である。スタック６１ａのデータを格納する位置はレジスタセット８０に含まれるスタックポインタ８２で指定される。
【００３０】
そして、関数の実行が終了すると、スタック６１ａにｐｕｓｈされた戻り命令アドレスがｐｏｐされ（４）、命令ポインタ８１に設定されることにより、関数からの戻りが行われる（５）。
【００３１】
このように、関数が呼び出される度にスタック６１ａに戻り命令アドレスが積まれる。そこで、unwind_stackプログラム２１は、スタック６１ａに積まれた一連の戻り命令アドレスを関数呼び出し関係の情報として呼び出し関係格納専用レジスタ８５に格納する。
【００３２】
なお、スタック６１ａには、関数呼び出し時に戻り命令アドレス以外のデータも格納される。図４は、関数呼び出し時にスタック６１ａに積まれるデータを説明するための図である。図４では、バイナリコード６１ｃが実行されている途中で関数ｍｙｆｕｎｃが呼ばれた場合を示す。また、図４において、ベースポインタ８３は、呼び出された関数の局所変数を格納する場所であるスタックフレームの１つ前の領域を指すポインタである。ベースポインタ８３が指す領域には、直前のベースポインタ８３の値が格納される。
【００３３】
図４に示すように、関数ｍｙｆｕｎｃが呼ばれると、スタック６１ａには、戻り命令アドレス９１と、直前のベースポインタの値９２と、ｍｙｆｕｎｃ用スタックフレーム９３が積まれる。ここで、戻り命令アドレス９１と直前のベースポインタの値９２は固定長であるが、スタックフレームの長さは、関数で使用される局所変数の個数に依存して可変である。そこで、unwind_stackプログラム２１は、直前のベースポインタの値９２を順番に辿ることによって、一連の戻り命令アドレスをスタック６１ａから取得する。
【００３４】
ベースポインタ８３とスタックフレームは、関数の呼び出し時に実行されるコードによりスタック６１ａに積まれる。図５Ａは、関数の呼び出し時に実行されるコードの一例を示す図である。図５Ａにおいて、ｐｕｓｈ  ｅｂｐは、ベースポインタ８３の値をスタック６１ａに保存する命令である。ｍｏｖ  ｅｂｐ，ｅｓｐは、現在のスタックフレームを指すようにベースポインタ８３の値を変更する。ｓｕｂ  ｅｓｐ，ｘは、局所変数の大きさの分スタックポインタ８２の値を減らす。なお、スタック６１ａには、上位アドレスから下位アドレスに向かってデータが積まれる。また、unwind_stackプログラム２１は、ｐｕｓｈ  ｅｂｐの前で呼ばれ、一連の戻り命令アドレスをスタック６１ａから取得する。
【００３５】
図５Ｂは、関数の戻り時に実行されるコードの一例を示す図である。図５Ｂにおいて、ｍｏｖ  ｅｓｐ，ｅｂｐは、局所変数を除去する。ｐｏｐ  ｅｂｐは、ベースポインタ８３の値を復帰する。ｒｅｔは、呼び出された関数から戻る。
【００３６】
図６は、サンプリングデータの形式を示す図である。図６に示すように、サンプリングデータの形式には、（ａ）パック形式と（ｂ）ハッシュ形式がある。サンプリングデータの先頭１ビットによりパック形式かハッシュ形式かが区別される。パック形式では、１つのサンプリングデータに固定長の戻り命令アドレスがＮ（Ｎは正の整数）個詰められる。なお、パック形式では、戻り命令アドレスは可逆圧縮されてもよい。
【００３７】
ハッシュ形式では、１つのサンプリングデータは、Ｎ個の戻り命令アドレスから計算されたハッシュ値である。図６（ｂ）において、ＨＡＳＨはハッシュ関数である。戻り命令アドレス1…NはＮ個の戻り命令アドレスを表す。ハッシュ形式では、サンプリングデータは可変長であり、サンプリングデータのサイズは小さくなる。
【００３８】
なお、ハッシュ形式では、図６（ｃ）に示すように、サンプリングデータを固定長とし、ハッシュ値を埋めて余ったスペースに、Ｎ個の戻り命令アドレスより前のＭ−Ｎ（ＭはＮ以上の正の整数）個の戻り命令アドレスをパック形式で詰める形式としてもよい。この形式は、１つのサンプリングデータがハッシュ値だけである形式と比較して、１つのサンプリングデータの情報量を増やすことができる。
【００３９】
また、図６では、先頭の１ビットを用いてパック形式かハッシュ形式かが区別されるが、パック形式では、戻り命令アドレスが詰められることからサンプリングデータに特徴があるので、先頭の１ビットは省略してもよい。
【００４０】
unwind_stackプログラム２１は、ハッシュ形式又はパック形式でＮ個の戻り命令アドレスをｍ個の呼び出し関係格納専用レジスタ８５に格納する。具体的には、unwind_stackプログラム２１は、Ｎ個の戻り命令アドレスをｍ個の呼び出し関係格納専用レジスタ８５に格納する際に乱数又は疑似乱数を用いてハッシュ形式又はパック形式を選択し、選択した形式で格納する。
【００４１】
なお、unwind_stackプログラム２１は、１ビットの選択フラグを関数毎に用意し、関数が呼び出されたときに選択フラグを書き換え、選択フラグが０のときはパック形式を選択し、選択フラグが１のときはハッシュ形式を選択してもよい。
【００４２】
図７は、unwind_stackプログラム２１の処理のフローを示すフローチャートである。図７に示すように、unwind_stackプログラム２１は、ハッシュ形式がパック形式かを決定し、繰り返し回数の上限Ｄを決定する（ステップＳ１）。ここで、Ｄ＝Ｎであるが、図６（ｃ）に示したハッシュ形式の場合、Ｄ＝Ｍである。
【００４３】
そして、unwind_stackプログラム２１は、作業用レジスタ1にベースポインタ８３の値をセットし（ステップＳ２）、スタックポインタ８２の参照先のメモリ６１の内容を戻り命令アドレス1として出力する（ステップＳ３）。そして、unwind_stackプログラム２１は、ｉが２以上Ｄ以下であるか否かを判定し（ステップＳ４）、ｉが２以上Ｄ以下でない場合には、ステップＳ９へ移動する。ここで、ｉは、unwind_stackプログラム２１が戻り命令アドレスを１つ取得する度に１増加する繰り返し変数であり、初期値は２である。
【００４４】
ｉが２以上Ｄ以下である場合には、unwind_stackプログラム２１は、作業用レジスタ2に作業用レジスタ1の内容のメモリ６１の内容をセットする（ステップＳ５）。この結果、作業用レジスタ2には、呼び出し側のベースポインタ８３の値がセットされる。
【００４５】
そして、unwind_stackプログラム２１は、作業レジスタ2の値は健全か否かを判定する（ステップＳ６）。作業レジスタ2の値はベースポインタ８３の値であるので、unwind_stackプログラム２１は、スタック６１ａのいずれかの領域を指しているか否かで健全性をチェックする。また、１つ前のベースポインタ８３の値は、現在のベースポインタ８３の値から１つの関数に関する情報を格納する領域分だけ大きい値であり、１つの関数に関する情報を格納する領域の大きさは、局所変数の数に依存するが、ある程度の範囲内である。したがって、unwind_stackプログラム２１は、このようなベースポインタ８３の値の特徴を利用して健全性をチェックする。
【００４６】
そして、作業レジスタ2の値が健全でない場合には、unwind_stackプログラム２１は、ステップＳ９へ移動する。一方、作業レジスタ2の値が健全である場合には、unwind_stackプログラム２１は、作業レジスタ2の参照アドレスに隣接するメモリ６１（例えば、（作業用レジスタ2の内容＋８）のアドレスになる）の内容を戻り命令アドレスiとして出力する（ステップＳ７）。なお、ここでは、アドレスは６４ビット＝８バイトとしている。そして、unwind_stackプログラム２１は、作業用レジスタ1に作業用レジスタ2の値をセットし（ステップＳ８）、ｉに１を加えてステップＳ４へ戻る。
【００４７】
そして、unwind_stackプログラム２１は、ステップＳ３及びステップＳ７で出力した（戻り命令アドレス1、・・・、戻り命令アドレスD）を入力し（ステップＳ９）、呼び出し関係の保持形式を判定する（ステップＳ１０）。その結果、呼び出し関係の保持形式がハッシュ形式である場合には、unwind_stackプログラム２１は、（戻り命令アドレス1、・・・、戻り命令アドレスD）をハッシュ関数に通した後、呼び出し関係格納専用レジスタ８５に格納する（ステップＳ１１）。一方、呼び出し関係の保持形式がパック形式である場合には、unwind_stackプログラム２１は、（戻り命令アドレス1、・・・、戻り命令アドレスD）をパック形式にて、呼び出し関係格納専用レジスタ８５に格納する（ステップＳ１２）。
【００４８】
このように、unwind_stackプログラム２１は、ベースポインタ８３の値を用いてスタック６１ａを辿って一連の戻り命令アドレスを取得し、ハッシュ形式又はパック形式で呼び出し関係格納専用レジスタ８５に格納する。また、呼び出し関係格納専用レジスタ８５に格納された一連の戻り命令アドレスは、性能収集用割込みプログラム２２によってメモリ６１に格納される。したがって、unwind_stackプログラム２１は、ハッシュ形式を使用しない場合と比較して、関数呼び出し関係の情報のメモリ６１での量を削減することができる。
【００４９】
次に、分析プログラム４について図８〜図１２を用いて説明する。図８は、分析プログラム４の機能構成を示す図である。図８に示すように、分析プログラム４は、サンプリング形式判別部４１と、ハッシュ部４２と、呼び出し関係復元部４３と、呼び出し関係別集計部４４とを有する。
【００５０】
なお、分析プログラム４は、サンプリングデータ記憶部３が記憶するサンプリングデータを２回のパスで処理する。第１のパスでは、分析プログラム４は、パック形式のサンプリングレコードのみを用いて逆ハッシュ表４３ａを作成する、ここで、サンプリングレコードとは、１つのサンプリングデータである。また、逆ハッシュ表４３ａは、ハッシュ値から関数呼び出し関係の情報を検索するためのテーブルである。第２のパスでは、分析プログラム４は、全サンプリングレコードを用いて関数呼び出し関係の集計を行う。そこで、以下では分析プログラム４の各機能部の処理をパス毎に説明する。
【００５１】
図９Ａは、分析プログラム４の第１のパスを説明するための図である。図９Ａに示すように、サンプリング形式判別部４１は、サンプリングデータ記憶部３からサンプリングレコードを読み出し、データ形式を判定する。そして、サンプリング形式判別部４１は、データ形式がパック形式の場合には、サンプリングレコードをハッシュ部４２に渡し、データ形式がハッシュ形式の場合には、サンプリングレコードに対する処理は行わない。
【００５２】
ハッシュ部４２は、サンプリングレコードに含まれる関数呼び出し関係の情報のハッシュ値を算出し、算出したハッシュ値と関数呼び出し関係の情報を呼び出し関係復元部４３に渡す。呼び出し関係復元部４３は、ハッシュ値と関数呼び出し関係の情報を対応付けて逆ハッシュ表４３ａに登録する。
【００５３】
図９Ｂは、分析プログラム４の第２のパスを説明するための図である。図９Ｂに示すように、サンプリング形式判別部４１は、サンプリングデータ記憶部３からサンプリングレコードを読み出し、データ形式を判定する。そして、サンプリング形式判別部４１は、データ形式がハッシュ形式の場合には、サンプリングレコードを呼び出し関係復元部４３に渡し、データ形式がパック形式の場合には、サンプリングレコードを呼び出し関係別集計部４４に渡す。
【００５４】
呼び出し関係復元部４３は、ハッシュ形式のサンプリングレコードに含まれるハッシュ値を用いて逆ハッシュ表４３ａを検索し、関数呼び出し関係の情報を復元する。そして、呼び出し関係復元部４３は、復元した関数呼び出し関係の情報をサンプリングレコードの形式にして呼び出し関係別集計部４４に渡す。
【００５５】
呼び出し関係別集計部４４は、サンプリング形式判別部４１及び呼び出し関係復元部４３から渡されたサンプリングレコードを関数呼び出し関係毎に集計し、集計結果を集計結果記憶部５に書き出す。
【００５６】
図１０Ａは、第１のパスの処理のフローを示すフローチャートである。図１０Ａに示すように、分析プログラム４は、サンプリングデータ記憶部３から全サンプリングレコードを順番に読み出し（ステップＳ２１）、各サンプリングレコードに対してステップＳ２１とステップＳ２６で挟まれた処理を行う。
【００５７】
なお、図１０Ａ〜図１１Ｂにおいて、「ｉ＝０，ＭａｘＮ，１」は、ｉを繰り返し変数として０から１ずつ増加させながらｉがＭａｘＮになるまで処理を繰り返すことを表す。ここで、ＭａｘＮはサンプリングレコードの数−１である。
【００５８】
分析プログラム４は、変数ＤにＤＡＴＡ［ｉ］をセットし（ステップＳ２２）、Ｄはパック形式か否かを判定する（ステップＳ２３）。ここで、ＤＡＴＡ［ｉ］は、ｉ番目のサンプリングレコードを表す。そして、Ｄがパック形式でない場合には、分析プログラム４は、次のサンプリングレコードを処理する。
【００５９】
一方、Ｄがパック形式である場合には、分析プログラム４は、変数ｖにＤの戻り命令アドレス1…Nから計算したハッシュ値をセットする（ステップＳ２４）。すなわち、ｖ＝ＨＡＳＨ（戻り命令アドレス1…N）とする。そして、分析プログラム４は、キーをｖ、値を戻り命令アドレスのリスト、すなわち、戻り命令アドレス1…Nとして、逆ハッシュ表４３ａに登録する（ステップＳ２５）。
【００６０】
このように、分析プログラム４は、第１のパスでパック形式のサンプリングレコードから逆ハッシュ表４３ａを作成することによって、第２のパスで逆ハッシュ表４３ａを用いてハッシュ形式のサンプリングレコードを復元することができる。
【００６１】
図１０Ｂは、第２のパスの処理のフローを示すフローチャートである。なお、図１０Ｂでは、ハッシュ形式は図６（ｃ）に示した形式である。図１０Ｂに示すように、分析プログラム４は、サンプリングデータ記憶部３から全サンプリングレコードを順番に読み出し、各サンプリングレコードに対してステップＳ３１とステップＳ３８で挟まれた処理を行う。
【００６２】
分析プログラム４は、変数ＤにＤＡＴＡ［ｉ］をセットし（ステップＳ３２）、Ｄはパック形式か否かを判定する（ステップＳ３３）。その結果、Ｄがパック形式である場合には、分析プログラム４は、ＤをファイルＤＡＴＡ＃２に格納する（ステップＳ３４）。すなわち、分析プログラム４は、ｉ番目のサンプリングレコードＤＡＴＡ＃２［ｉ］＝Ｄとする。
【００６３】
一方、Ｄがパック形式でない場合には、分析プログラム４は、Ｄ．ＨＡＳＨをキーとして、逆ハッシュ表４３ａを検索し、検索結果を戻り命令アドレスリストＬとする（ステップＳ３５）。ここで、Ｄ．ＨＡＳＨは、ハッシュ形式のサンプリングレコードＤのハッシュ値の部分である。すなわち、逆ハッシュ表４３ａを検索する関数をｓｅａｒｃｈとすると、戻り命令アドレスリストＬ＝ｓｅａｒｃｈ（Ｄ．ＨＡＳＨ）である。
【００６４】
そして、分析プログラム４は、２つのリストＬとＤ．ＡＤＤＲＳとを連結し、復元したサンプリングレコードＲＥＳＴＯＲＥＤを生成する（ステップＳ３６）。ここで、Ｄ．ＡＤＤＲＳは、ハッシュ形式のサンプリングレコードＤのハッシュ値を除いた部分である。すなわち、リストを連結する関数をｃｏｎｃａｔとすると、ＲＥＳＴＯＲＥＤ＝ｃｏｎｃａｔ（Ｌ，Ｄ．ＡＤＤＲＳ）である。
【００６５】
そして、分析プログラム４は、ＤＡＴＡ＃２［ｉ］にＲＥＳＴＯＲＥＤを格納する（ステップＳ３７）。すなわち、ＤＡＴＡ＃２［ｉ］＝ＲＥＳＴＯＲＥＤである。
【００６６】
そして、全サンプリングレコードの処理が終了すると、分析プログラム４は、ＤＡＴＡ＃２に含まれる全サンプリングレコードを関数呼び出し関係別に集計する（ステップＳ３９）。
【００６７】
このように、分析プログラム４は、ハッシュ形式のサンプリングレコードを逆ハッシュ表４３ａを用いて復元することによって、全サンプリングレコードを関数呼び出し関係別に集計することができる。
【００６８】
図１１Ａは、サンプリング結果の集計処理の第１の例を示すフローチャートである。図１１Ａは、戻り命令アドレス1別にサンプリング結果を集計する処理を示す。図１１Ａに示すように、分析プログラム４は、ファイルＤＡＴＡ＃２から全サンプリングレコードを順番に読み出し、各サンプリングレコードに対してステップＳ４１とステップＳ４７で挟まれた処理を行う。
【００６９】
すなわち、分析プログラム４は、変数ＤにＤＡＴＡ＃２［ｉ］をセットし（ステップＳ４２）、Ｘに戻り命令アドレス1が存在するか否かを判定する（ステップＳ４３）。ここで、Ｘは、キーを戻り命令アドレス、値を出現回数とするハッシュ表である。Ｄ．ＡＤＤＲ［ｋ］は、サンプリングレコードＤの戻り命令アドレスkである（ｋは１〜Ｎの整数）。ｅｘｉｓｔ（Ｘ，Ｋ）は、ハッシュ表ＸにキーＫが存在すれば値がｔｒｕｅとなり、存在しなければ値がｆａｌｓｅとなる関数である。
【００７０】
そして、ハッシュ表Ｘに戻り命令アドレス1が存在しない場合には、分析プログラム４は、ハッシュ表ＸにキーがＤ．ＡＤＤＲ［１］であって値が０であるエントリを追加する（ステップＳ４４）。ここで、ｉｎｓｅｒｔ（Ｘ，Ｋ，ＶＡ）は、ハッシュ表ＸにキーがＫであって値がＶＡであるエントリを追加する関数である。
【００７１】
そして、分析プログラム４は、ハッシュ表ＸからキーがＤ．ＡＤＤＲ［１］である値を取得してＶに格納する（ステップＳ４５）。ここで、ｌｏｏｋｕｐ（Ｘ，Ｋ）は、ハッシュ表ＸからキーがＫである値を取得する関数である。
【００７２】
そして、分析プログラム４は、ハッシュ表ＸのキーがＤ．ＡＤＤＲ［１］である値をＶ＋１に更新する（ステップＳ４６）。ここで、ｕｐｄａｔｅ（Ｘ，Ｋ，ＶＡ）は、ハッシュ表ＸのキーがＫである値をＶＡに更新する関数である。
【００７３】
このように、分析プログラム４は、Ｄ．ＡＤＤＲ［１］別に出現回数を数えることで、戻り命令アドレス1別にサンプリング結果を集計することができる。
【００７４】
図１１Ｂは、サンプリング結果の集計処理の第２の例を示すフローチャートである。図１１Ｂは、戻り命令アドレス1,…,Nのサンプリング数の内訳を算出するためにトライ木を作成する処理を示す。ここで、トライ木とは、木構造上のノードの位置とキーが対応付られる木である。後述する図１２にトライ木の一例を示す。
【００７５】
図１１Ｂに示すように、分析プログラム４は、ファイルＤＡＴＡ＃２から全サンプリングレコードを順番に読み出し、各サンプリングレコードに対してステップＳ５１とステップＳ５７で挟まれた処理を行う。
【００７６】
すなわち、分析プログラム４は、変数ＤにＤＡＴＡ＃２［ｉ］をセットし（ステップＳ５２）、ＴにＤ．ＡＤＤＲＳが存在するか否かを判定する（ステップＳ５３）。ここで、Ｔは、キーを戻り命令アドレスリスト、値を出現回数とするトライ木である。ｅｘｉｓｔ（Ｔ，Ｋ）は、トライ木にキーＫが存在すれば値がｔｒｕｅとなり、存在しなければ値がｆａｌｓｅとなる関数である。
【００７７】
そして、トライ木にＤ．ＡＤＤＲＳが存在しない場合には、分析プログラム４は、トライ木にキーがＤ．ＡＤＤＲＳであってトライ木のパスの全ノードの値が０であるエントリを追加する（ステップＳ５４）。ここで、ｉｎｓｅｒｔ（Ｔ，Ｋ）は、トライ木ＴにキーがＫであってトライ木のパス上の全ノードの値が０であるエントリを追加する関数である。
【００７８】
そして、分析プログラム４は、トライ木からキーがＤ．ＡＤＤＲＳであるパスの全ノードの値を取得してそれぞれｖ1、ｖ2、．．．、ｖNに格納する（ステップＳ５５）。ここで、ｌｏｏｋｕｐ（Ｔ，Ｋ）は、トライ木ＴからキーがＫであるパスの全ノードの値を取得する関数である。
【００７９】
そして、分析プログラム４は、トライ木のキーがＤ．ＡＤＤＲＳであるパスの各ノードの値をそれぞれｖ1＋１、ｖ2＋１、・・・、ｖN＋１に更新する（ステップＳ５６）。ここで、ｕｐｄａｔｅ（Ｔ，Ｋ，ＶＬ）は、トライ木ＴのキーがＫであるパスの各ノードの値を値のリストＶＬの各値に更新する関数である。
【００８０】
このように、分析プログラム４は、Ｄ．ＡＤＤＲＳのパスのノード別に出現回数を数えることで、戻り命令アドレス1,…,Nのサンプリング数の内訳を算出することができる。
【００８１】
図１２は、トライ木の一例を示す図である。図１２は、６つのサンプリングレコードＤＡＴＡ＃２［０］〜ＤＡＴＡ＃２［５］から作成されるトライ木を示す。ノードは円で図示されており、ノード内に書かれた数が命令アドレスを示している。図１２に示すように、トライ木は、ノード1をルートとするサブ木とノード5をルートとするサブ木とから構成される。そして、例えばノード1をルートとするサブ木は、ノード2をルートとするサブ木とノード5のリーフとから構成される。そして、ＤＡＴＡ＃２［１］＝（１，５）は、ノード1→ノード5のパスに対応する。
【００８２】
ノード1は、ＤＡＴＡ＃２［０］＝（１，２，３）、ＤＡＴＡ＃２［１］＝（１，５）及びＤＡＴＡ＃２［３］＝（１，２，３，４，７）に出現するので、出現回数は３である。図１２では、出現回数は、各ノードの右の四角に囲まれた数で示される。また、例えば、ノード6の出現回数２は、先頭が（５，６）で始まる出現が２回あることを表わしている。
【００８３】
次に、性能情報収集プログラム１を実行するコンピュータの構成について説明する。図１３は、性能情報収集プログラム１を実行するコンピュータの構成を示す図である。図１３に示すように、コンピュータ６０は、メモリ６１と、ＣＰＵ６２と、ＨＤＤ６３と、ＬＡＮインタフェース６４と、入出力インタフェース６５と、ＤＶＤドライブ６６とを有する。
【００８４】
メモリ６１は、プログラムやプログラムの実行途中結果などを記憶するＲＡＭ（RandomAccess  Memory）であり、ＣＰＵ６２は、メモリ６１からプログラムを読み出して実行する中央処理装置である。ＨＤＤ６３は、プログラムやデータを格納するディスク装置であり、ＬＡＮインタフェース６４は、コンピュータ６０をＬＡＮ経由で他のコンピュータに接続するためのインタフェースである。入出力インタフェース６５は、マウスやキーボードなどの入力装置及び表示装置を接続するためのインタフェースであり、ＤＶＤドライブ６６は、ＤＶＤの読み書きを行う装置である。
【００８５】
そして、コンピュータ６０において実行される性能情報収集プログラム１は、ＤＶＤに記憶され、ＤＶＤドライブ６６によってＤＶＤから読み出されてコンピュータ６０にインストールされる。あるいは、性能情報収集プログラム１は、ＬＡＮインタフェース６４を介して接続された他のコンピュータシステムのデータベースなどに記憶され、これらのデータベースから読み出されてコンピュータ６０にインストールされる。そして、インストールされた性能情報収集プログラム１は、ＨＤＤ６３に記憶され、メモリ６１に読み出されてＣＰＵ６２によって実行される。
【００８６】
上述してきたように、実施例では、unwind_stackプログラム２１は、関数呼び出しが行われると、スタック６１ａが記憶する一連の戻り命令アドレスを関数呼び出し関係の情報として呼び出し関係格納専用レジスタ８５に格納する。このとき、unwind_stackプログラム２１は、ハッシュ形式かパック形式のいずれかを選択し、選択した形式で関数呼び出し関係の情報を呼び出し関係格納専用レジスタ８５に格納する。したがって、性能情報収集プログラム１は、全てをパック形式で格納する場合と比較して、関数呼び出し関係の情報の量を削減することできる。
【００８７】
また、実施例では、分析プログラム４は、パック形式のサンプリングレコードから逆ハッシュ表４３ａを作成し、逆ハッシュ表４３ａを用いてハッシュ形式のサンプリングレコードを復元する。したがって、性能情報収集プログラム１は、関数呼び出し関係の情報の量を削減するとともに、サンプリングレコード数の減少を防ぐことができる。
【００８８】
また、実施例では、unwind_stackプログラム２１は、関数呼び出し関係の情報を呼び出し関係格納専用レジスタ８５に格納する。したがって、性能収集用割込みプログラム２２は、簡単に関数呼び出し関係の情報を収集することができる。
【００８９】
なお、実施例では、関数呼び出し時にスタック６１ａに戻り命令アドレス、直前のベースポインタの値、局所変数が積まれる場合について説明した。しかしながら、本発明は、これに限定されるものではなく、他のデータがスタック６１ａにさらに積まれる場合にも同様に適用することができる。
【００９０】
また、実施例では、ハッシュ関数を用いて関数呼び出し関係の情報を圧縮する場合について説明した。しかしながら、本発明は、これに限定されるものではなく、ハッシュ関数以外の非可逆圧縮関数を用いて関数呼び出し関係の情報を圧縮する場合にも同様に適用することができる。
【符号の説明】
【００９１】
１    性能情報収集プログラム
２    サンプリングプログラム
３    サンプリングデータ記憶部
４    分析プログラム
５    集計結果記憶部
２１    unwind_stackプログラム
２２    性能収集用割込みプログラム
４１    サンプリング形式判別部
４２    ハッシュ部
４３    呼び出し関係復元部
４３ａ    逆ハッシュ表
４４    呼び出し関係別集計部
６０    コンピュータ
６１    メモリ
６１ａ    スタック
６１ｂ    ヒープ
６１ｃ    バイナリコード
６２    ＣＰＵ
６２ａ    ＰＭＵ
６３    ＨＤＤ
６４    ＬＡＮインタフェース
６５    入出力インタフェース
６６    ＤＶＤドライブ
７１    性能収集対象コード
７１ａ    unwind_stackコード
７２    ハッシュ関数コード
７３    性能収集用割込みコード
７４    サンプリングバッファ
８０    レジスタセット
８１    命令ポインタ
８２    スタックポインタ
８３    ベースポインタ
８４    汎用レジスタ
８５    呼び出し関係格納専用レジスタ
９１    戻り命令アドレス
９２    直前のベースポインタの値
９３    ｍｙｆｕｎｃ用スタックフレーム
【図１】
0006540340.tif 000002
【図２】
0006540340.tif 000003
【図３】
0006540340.tif 000004
【図４】
0006540340.tif 000005
【図５Ａ】
0006540340.tif 000006
【図５Ｂ】
0006540340.tif 000007
【図６】
0006540340.tif 000008
【図７】
0006540340.tif 000009
【図８】
0006540340.tif 000010
【図９Ａ】
0006540340.tif 000011
【図９Ｂ】
0006540340.tif 000012
【図１０Ａ】
0006540340.tif 000013
【図１０Ｂ】
0006540340.tif 000014
【図１１Ａ】
0006540340.tif 000015
【図１１Ｂ】
0006540340.tif 000016
【図１２】
0006540340.tif 000017
【図１３】
0006540340.tif 000018