Rational Quantify/Rational PureCoverage インタープリタ インターフェイス (QII) は主に翻訳された環境 (Visual Basic や Java など) で、インストゥルメントされたコードの実行を模倣するための Quantify/PureCoverage のランタイムを実行することを目的としています。 また、プロファイリング機能をツールに挿入するために言語ベンダーが使用することもできます。ここではこの API の一般的なユース ケースについて説明します。
メモ: この API は最適なパフォーマンスを発揮するように設計されており、実行の高速化を目的として、重要度の低い整合チェックは省略されています。 入力されたデータが有効で確証済みであると推測します。 無効なデータ、不正なポインタ、行番号の矛盾は、実行中に Quantify や PureCoverage を破壊する可能性があります。 注意深くご使用ください。
一般的なユース ケースには、プロファイルするインタープリタ実行コードが関与します。 この API は言語システムが手順ベースであると仮定します。 ソース レベルの詳細情報に関しては、行テーブルを提供することができます (以下の行番号テーブルを参照してください)。
この API に対して動的リンクを使用することを推奨します。 ランタイム時にコードを QII にリンクするために LoadLibrary と GetProcAddress の呼び出しを使用してください。 プログラムを Quantify か PureCoverage のどちらかのみと併用する際には静的リンクを使用することができます。 動的リンクはこの API に対する最高の柔軟性を提供します。
Qprof.dll と Cprof.dll は通常 Quantify や PureCoverage の製品ディレクトリにある PATH 変数にリストされたディレクトリに保存することを推奨します。
QII の関数のプロトタイプは QProf.h\CProf.h にリストされています。またこのファイルには一部のプログラミングのヒントが含まれています。
この機能の呼び出しは、他の呼び出しが QII に対して行われる前に行う必要があります。 この呼び出しは Quantify (QProf.dll 用) か PureCoverage (Cprof.dll 用) を初期化し、製品の初期化オプションを設定します。
int _EXT_REF qprof_initialize(const char *initial_options,
void(*callback_get_method_info)(qprof_MethodID));
initial_options - Quantify か PureCoverage の任意のランタイム オプション。 オプションや構文については製品のマニュアルをご覧ください。
callback_get_method_info - 不明なメソッド ID の修正に使用されるコールバック機能。 この機能はランタイムが未登録のメソッド ID に対するメソッド エントリを検出した際に QII により呼び出されます(qprof_register_method_id を参照してください)。 プログラムの実行中に呼び出す、すべての使用可能なメソッドの ID を登録すると、これは発生しません。 すべてのメソッドの ID を登録しないと、メソッドが呼び出された際に qprof_register_method_id を呼び出す機会が与えられます。
これが実行中の最終呼び出しです。 重要: プログラムが破壊される可能性があるため、この呼び出しの後には他の QII 機能を呼び出さないでください。 この呼び出しにより Quantify や PureCoverage がランタイムの情報を要約し、その結果を表示します。
void _EXT_REF qprof_shutdown(void);
Quantify/PureCoverage のランタイム オプションを取得します。
qprof_get_option を使用して Quantify/PureCoverage オプション システムにアクセスすることができます。 この機能は "void *" を返し、ユーザーはこれを文字列のオプションに対しては "const char *" に、数字のオプションに対しては "bool"、"int"、"unsigned" のいずれかにキャストする必要があります。 該当するオプションのタイプを確認し、正しくキャストする必要があります。 存在しないオプションを指定すると機能は NULL を返し、有効なオプションに対する 0 の値と区別できません (またデフォルトのオプションが選択さたか、手動で設定されたかが判断できません)。
void * _EXT_REF qprof_get_option(const char *optionName);
optionName - Quantify/PureCoverage のランタイム オプション名を含む null により中断された文字列。
void * - オプション値が保管されたバッファへのポインタ。 値のデータ タイプはオプションに必要なデータ タイプに整合する必要があります。
void _EXT_REF qprof_thread_create(qprof_ThreadID id);
id - 固有のスレッド ID (符号を含まない)
ASCII の文字列を現在のスレッドと関連づけます。
void _EXT_REF qprof_set_thread_name(const char *new_name);
new_name - スレッド名として使用する文字列。
スレッドの破壊を通知します。
void _EXT_REF qprof_thread_destroy(qprof_ThreadID id);
id- 同じ ID が qprof_thread_create で使用されました。
現在のメソッド ID を取得します。
qprof_MethodID _EXT_REF qprof_current_method_id(void);
戻り値:
qprof_MethodID- 現在のメソッド ID (現在のスレッドに入力した最終のメソッド)。
void _EXT_REF qprof_register_method_id(qprof_MethodID id,
const char *demangled_name,
const char *class_name,
int flags,
const char *source_file,
const qprof_LineInfo *line_number_table,
int line_number_size);
id - 固有のメソッド ID です。
demangled_name - メソッド (機能) 名。 この名前はこの機能のすべてのプロファイラ データで使用されます。
class_name - この方法がクラスに属す場合はクラス名。その他の場合は NULL。
flags - メソッドの特性を示すフラグ。
QPROF_METHOD_FLAGS_NONE – not defined
QPROF_METHOD_FLAGS_BLOCKS - メソッドが実行を妨げます
QPROF_METHOD_FLAGS_WAITS – synchronous method waiting for system return
source_file - ソース ファイル名
line_number_table- 行番号テーブル (以下を参照)
line_number_size - 行番号テーブルのエントリ数
line_number_table の引数は qprof_LineInfo structs の列か、同じレイアウトのものをポイントする必要があります。 各エントリは特定の行番号により生成された開始コードのオフセット値を示します。 開始オフセットから次のオフセットまでのオフセットでのコードは、示された行からのものであると仮定されます。
例:
0 15
7 16
12 19
このテーブルは、0-6 のコード オフセットは行 15 と、7-11 のコード オフセットは行 16 と、12 以上は行 19 と関連付けられることを意味します。テーブルはコード オフセットの昇順に並べ替えられます。 行番号は固有や昇順である必要はありません。オプティマイザによりどのような操作も可能です。 テーブルがコード オフセット 0 で始まらない場合、0 のオフセットから最初の値までは最初の行番号に関連付けられます。
機能エントリを通知します。
void _EXT_REF qprof_record_fn_entry(qprof_MethodID method_id, qprof_StackID stack_id);
method_id - 固有のメソッド ID (qprof_register_method_id の呼び出しと同様)。
Stack_id- スタック ID (以下参照)。
これは決定して常時使用する必要のある ID 値です。 機能エントリを報告する際に、入力する機能の qprof_MethodID と、そのときのスタック ポインタの場所を示す qprof_StackID 値を渡す必要があります。 機能の終了を正しく報告するために qprof_StackID を記録する必要があります。 残念ながら、StackID の使用法は複雑です。 機能の入力時刻で数値を渡したり、同じ数値を機能終了時刻に渡す作業のように簡単ではありません。 実際には、機能の入力時にユーザーが存在するフレームを識別するためにある数値(X と呼びます)を渡し、その後に子機能の終了時に「フレーム X に戻りました」というメッセージと共に同じ数値を渡します。
例:
main() {
fun_one();
fun_two();
}
fun_one() {
fun_three();
}
fun_two() {
// empty
}
main への入力では、例えばそのスタック フレームを表すために qprof_StackID 65 を選んだ場合、 このプログラムのレポートとスタック ID の順序は次のようになります:
fn_entry(main, 65)
fn_entry(fun_one, 66)
fn_entry(fun_three, 67)
fn_exit(66)
fn_exit(65)
fn_entry(fun_two, 66)
fn_exit(65)
fn_exit(xx)
例で正しい値が表示されないため、最後の fn_exit は "xx" です。
機能 "main" のスタック フレームは qprof_StackID 値 65 により識別されます。従って qprof_StackID 値 65 は一貫して "main に戻りました" ということを意味します。 これは fun_one のフレームを識別する qprof_StackID 値 66 についても同様です。
スタックはスレッド単位のオブジェクトであるため、qprof_StackID 値はスレッド単位で保持する必要があります。 StackID 値はすべてのスレッドで固有である必要はありません。
一部の実装では実際のコンピュータ SP 値を StackID 値として使用できることにご注意ください。 これは、ネイティブ C コードの実行スタックが、プロファイルしようとしている環境に保持された「仮想」スタックと異なる場合には該当しません。 スタック ID 値は昇順、降順のどちらでも数えることができることにご注意ください。
実際には fn_exit の通知を「この値に ID が一致するフレームに到達するまでフレームをシャドウ スタックで書き続ける」と解釈することができます。 最後の fn_entry から数レベル上層にあるフレームで実行の継続を可能とする例外の処理方法は、以下の 2 つのいずれかです。 最初の方法は、アンワインドするフレームごとにプロファイルする環境に "fn_exit" 通知させ、通知を QProf へ渡す方法です。 もう 1 つの方法は、実行が継続するフレームのスタック ID 値を含む 1 つの「例外通知」を環境に通知させる方法です。 その値の使用後に fn_exit を呼び出すことができます。これによりシャドウ スタックが応答レベルまで展開します。
メモ: 実際のスタック フレームを識別するために 0 の StackID を使わないで下さい。これは内部で QProf に対する特別な意味を持ちます。 また誤って以前の fn_entry に対応しない fn_exit を StackID に渡すと、シャドウ スタックは完全に展開されます。 これはアルゴリズムの機能でなく副作用です。 意図的にこれを行うと、ライブラリがクラッシュすることがあります。
シャドウ スタックの上に保存される機能の終了を通知します。
void _EXT_REF qprof_record_fn_exit(qprof_StackID id);
Stack_id - Stack id (上記の Stack Id を参照)。
現在の呼び出しの記録回数カウンタ値です。
void _EXT_REF qprof_record_counts(qprof_Counts arg);
arg - 現在のカウンタ値
基本ブロックの記録回数値です。
void _EXT_REF qprof_record_bb_counts(int bb_num, qprof_Counts arg);
bb_num - 基本ブロック数 (行番号テーブルのオフセット)
arg - カウンタ値
基本ブロック bb_num の記録回数カウンタ値です。 これはシステム クロックを使用して記録します。
void _EXT_REF qprof_record_bb_time(int bb_num);
bb_num - 基本ブロック数 (行番号テーブルのオフセット)
Copyright(C) IBM Corporation. 2001,2007. All rights reserved.
Rational、Rational のロゴ、Quantify、PureCoverage は、IBM Corporation の米国およびその他の国における商標または登録商標です。