プログラムのパフォーマンス解析

第 4 章 従来のプロファイリングツール

この章では、プログラムの動作時間を測定したり、解析対象となるパフォーマンスデータを得るための標準的なユーティリティについて解説します。prof および gprof は、SPARC プラットフォームおよび x86 プラットフォームの Solaris バージョン 2.5.1、2.6 および 7 に付属のプロファイリングツールです。また、tcov はコードカバレージツールです。

ツールの中には、どんなプログラミング言語で記述されたモジュールに対しても動作するものと、C プログラミング言語とのみ動作するものがあります。言語に関する詳細情報については、それぞれのツールの項を参照してください。

この章は、以下の項目から構成されています。

基本概念

profgprof、 および tcov は Sun WorkShop の開発環境を拡張し、パフォーマンスデータの収集および利用を可能にします。prof はフラットファイル形式のプログラムプロファイルを生成し、gprof はコールグラフプロファイルを作成します。また、tcov は、どの行がどのくらいの頻度で使用されたかを示すステートメントレベルの情報をソースファイルのコピーに生成します。

表 4-1 に、標準的なパフォーマンスプロファイリングツール一覧を示します。

表 4-1 パフォーマンスプロファイリングツール

コマンド 

動作 

prof

各関数に制御が渡る正確な回数とともに、プログラムによって使用されるCPU 時間の統計的プロファイルを生成します。このツールは Solaris オペレーティングシステム環境に付属しています。 

gprof

各関数に制御が渡る正確な回数、およびプログラムのコールグラフの各 arc (呼び出す側と呼び出される側の組み合わせ) 上で制御が受け渡しされる回数とともに、プログラムによって使用される CPU 時間の統計的プロファイルを生成します。このツールは Solaris オペレーティングシステム環境に付属しています。 

tcov

プログラムの各ステートメントが実行される正確な回数を生成します。tcov には、オリジナルの tcov と、 tcov Enhanced の2バージョンがあります。これら2つのバージョンは、出力で使用される生データを生成する実行時サポートが異なります。オリジナルの tcov は -xa コンパイラオプションまたは -a オプション(C++)を使ってコンパイルされたプログラムからデータを取得します。 

prof によるプログラムプロファイルの生成

prof はプログラムによって使用される CPU 時間の統計プロファイルを生成し、プログラム中の各関数へ制御が渡される回数をカウントします。さらに詳細なデータは、コールグラフプロファイルおよびコードカバレージツールによって提供されます。

prof を利用するための手順は以下の 3 段階となっています。

  1. prof 用のプログラムをコンパイルします。

  2. プログラムを実行して、プロファイルデータファイルを作成します。

  3. prof を使ってデータを要約したレポートを生成します。

prof によるプロファイリング用のプログラムをコンパイルするには、コンパイラに対して -p オプションを使用してください。たとえば、index.assist.c という名前の C のソースファイルをプロファイリング用にコンパイルするには、以下のコンパイラコマンドを使用します。


% cc -p -o index.assist index.assist.c

コンパイラは index.assist という名前のプログラムを作成します。

次に、この index.assist プログラムを実行してください。プログラムを実行するたびに、プロファイリングデータが mon.out と呼ばれるファイルに送られます。プログラムを実行するたびに、新しい mon.out が生成され、古いバージョンは上書きされます。

最後に prof コマンドを使ってレポートを生成します。


% index.assist 
% ls mon.out
mon.out
% prof index.assist

prof の出力は、以下の例のようになります。

%Time 

Seconds 

Cumsecs 

#Calls 

msecs/call 

Name  

19.4 

3.28 

3.28 

11962 

0.27 

compare_strings  

15.6 

2.64 

5.92 

32731 

0.08 

_strlen  

12.6 

2.14 

8.06 

4579 

0.47 

__doprnt  

10.5 

1.78 

9.84 

 

 

mcount 

9.9 

1.68 

11.52 

6849 

0.25 

_get_field  

5.3 

0.90 

12.42 

762 

1.18 

_fgets  

4.7 

0.80 

13.22 

19715 

0.04 

_strcmp  

4.0 

0.67 

13.89 

5329 

0.13 

_malloc  

 3.4 0.57 14.46 11152 0.05 _insert_index_entry
 3.1 0.53 14.99 11152 0.05 _compare_entry
 2.5 0.42 15.41 1289 0.33 lmodt
 0.9 0.16 15.57 761 0.21 _get_index_terms
 0.9 0.16 15.73 3805 0.04 _strcpy
 0.8 0.14 15.87 6849 0.02 _skip_space
 0.7 0.12 15.99 13 9.23 _read
 0.7 0.12 16.11 1289 0.09 ldivt
 0.6 0.10 16.21 1405 0.07 _print_index
 . . (以下の出力はそれほど重要ではありません)

prof 出力の例

この出力結果からは、このプログラムの実行時間のほとんどは compare_strings ルーチンに費やされ、次に、_strlen ライブラリルーチンに費やされていることがわかります。このプログラムを改良するためには、compare_strings 関数に専念する必要があります。

それでは次に、このプロファイリング実行結果を解読していきます。結果は以下の列見出しの下に一覧表示されます。

%Time -- プログラムのこのルーチンによって消費される CPU 時間の合計におけるパーセンテージ。

Seconds -- この関数によって占められる CPU 時間の合計。

Cumsecs -- この関数およびその上位にリストされている関数によって占められる CPU 時間の総合計 (秒) 。

#Calls -- このルーチンが呼び出される回数。

msecs/call -- このルーチンが呼び出されるたびに消費する平均ミリ秒数。

Name -- ルーチンの名前

このプロファイルデータからはいったいどんな結果が導き出されるのでしょうか。compare_strings 関数は、プログラムの総時間の約 20 パーセントを消費しています。そこで、この index.assist を改良するには、compare_strings が使用しているアルゴリズムを改良するか、compare_strings の呼び出し回数を減らすという方法が考えられます。

このフラットコールグラフからは compare_strings がかなり強い再帰性を持つかはわかりませんが、次の項で説明するコールグラフプロファイルを利用することによって、こうした情報も得ることができます。ここで紹介しているケースの場合は、アルゴリズムの改良によって呼び出し回数も減少します。


注 -

Solaris オペレーティング環境のバージョン 2.6 および 7 では、複数の CPU を使用するプログラムに対して CPU 時間のプロファイルは正確ですが、カウントはロックされていないため、関数のカウントの正確さには影響があるかもしれません。


gprof によるコールグラフプロファイルの生成

prof のフラットプロファイルは、パフォーマンス改善のために価値のあるデータを提供しますが、コールグラフプロファイルを利用すれば、さらに詳細な解析を実行できます。コールグラフプロファイルは、どのモジュールがほかのモジュールから呼び出されているか、どのモジュールがほかのモジュールを呼び出しているかを識別する一覧表を表示します。ときには、呼び出しをすべて削除することで、パフォーマンスが改善される場合もあります。


注 -

gprof は関数内の時間を、各 arc が往復する回数に比例して、呼び出し側に割り当てます。しかし、すべての呼び出しで同じ動作をするわけではないため、こうした動作は誤った仮定に陥る可能性もあります。


prof 同様、gprof もプログラムが使用する CPU タイムの統計的プロファイルを生成し、関数に制御が渡される回数をカウントします。gprof はさらに、プログラムのコールグラフにおいて各 arc 上で制御が受け渡される回数もカウントします。arc とは、呼び出す側と呼び出される側の組み合わせを指します。


注 -

Solaris オペレーティング環境のバージョン 2.6 および 7 では、複数の CPU を使用するプログラムに対してCPU 時間のプロファイルは正確ですが、カウントはロックされていなため、関数のカウントの正確さには影響があるかもしれません。


gprof を利用するための手順は以下の 3 段階となっています。

  1. gprof 用のプログラムをコンパイルします。

  2. プログラムを実行して、プロファイルデータファイルを作成します。

  3. gprof を使ってデータを要約したレポートを生成します。

コールグラフプロファイリング用のプログラムをコンパイルするには、C コンパイラに対しては -xpg オプションを、Fortran コンパイラに対しては -pg オプションを使用してください。以下に例を示します。


% cc -xpg -o index.assist index.assist.c

この結果 index.assist プログラムが実行可能になりました。gprof 用にコンパイルされたプログラムを実行するたびに、コールグラフプロファイルデータが gmon.out という名前のファイルに送られます。そのプログラムを実行するたびに、新しい gmon.out が作成されます。

プロファイルの結果レポートを生成するには、gprof コマンドを使用します。gprof の出力はかなり大量になる可能性があります。そのため、結果をファイルにリダイレクトすると、レポートはかなり読みやすくなるでしょう。gprof の出力を /tmp/g.output というファイルにリダイレクトするには、以下の一連のコマンドを使用してください。


% index.assist 
% ls gmon.out 
gmon.out
% gprof index.assist > /tmp/g.output

gprof の出力は以下の 2 つの主要項目から構成されます。

gprof の出力には、要約の各部分がどのような意味を持っているかの説明も含まれます。gprof はさらに標本収集の細分性を示します。

granularity: each sample hit covers 4 byte(s) for 0.07% of 14.74 seconds

ここでは、4 byte(s) とは 1 命令の解像度を意味しています。つまり、各標本が全実行時間の 0.07 パーセントであり、CPU 時間が 10 ミリ秒であることを意味します。

以下に、コールグラフプロファイルの一部を示します。

index 

%time 

self 

descendents 

called/total parents 

called+self 

called/total children  

name 

index 

-----------------------------------------------  

 

 

0.00 

14.47 

1/1 

start 

[1]  

[2] 

98.2 

0.00 

14.47 

_main 

[2]  

 

 

0.59 

5.70 

760/760 

_insert_index_entry 

[3]  

 

 

0.02 

3.16 

1/1 

_print_index 

[6]  

 

 

0.20 

1.91 

761/761 

_get_index_terms 

[11]  

 

 

0.94 

0.06 

762/762 

_fgets 

[13]  

 

 

0.06 

0.62 

761/761 

_get_page_number 

[18]  

 

 

0.10 

0.46 

761/761 

_get_page_type 

[22]  

 

 

0.09 

0.23 

761/761 

_skip_start 

[24]  

 

 

0.04 

0.23 

761/761 

_get_index_type 

[26]  

 

 

0.07 

0.00 

761/820 

_insert_page_entry 

[34]  

-----------------------------------------------  

 

 

 

 

10392 

_insert_index_entry 

[3]  

 

 

0.59 

5.70 

760/760 

_main 

[2]  

[3] 

42.6 

0.59 

5.70 

760+10392 

_insert_index_entry 

[3]  

 

 

0.53 

5.13 

11152/11152 

_compare_entry 

[4]  

 

 

0.02 

0.01 

59/112 

_free 

[38]  

 

 

0.00 

0.00 

59/820 

_insert_page_entry 

[34]  

 

 

 

 

10392 

_insert_index_entry 

[3] 

-----------------------------------------------  

この index.assist プログラムの入力ファイルのデータには 761 行が含まれていると想定すると、以下の結論が導き出されます。

tcov によるステートメントレベルの解析

tcov は、プログラムの実行方法に関する行単位の情報を提供します。tcov はソースファイルのコピーを作成し、そこにどの行がどれくらいの頻度で使用されているかを示す注釈を挿入します。また、基本的なブロックについての情報も集約します。tcov は時間ベースのデータは生成しません。

tcov を利用するための手順は以下の 3 段階となっています。

  1. tcov の実験データ作成用に、プログラムをコンパイルします。

  2. 実験を実行します。

  3. tcov を使って、プログラムの各ステートメントの実行カウントの集計を生成します。

tcov 用のコンパイル

コードカバレージ用にプログラムをコンパイルするには、C コンパイラに対して -xa オプションを使用します。index.assist という名前のプログラムを例として使用する場合、以下のコマンドによって、tcov 用のコンパイルを行ってください。

% cc -xa -o index.assist index.assist.c

C++ または f77 コンパイラに対しては、-a コンパイラオプションを使用します。

C コンパイラは index.assist.c に存在する基本ブロックについてのデータベースエントリを含む index.assist.d ファイルを生成します。プログラム index.assist が実行され、終了した時点で、コンパイラは index.assist.d ファイルを更新します。


注 -

tcov は C および C++ プログラムとは動作しますが、#line または #file 指示が含まれるファイルはサポートしません。tcov は、#include ヘッダーファイルのコードのテストカバレージ解析も行うことができません。-xa (C)、-a (その他のコンパイラ)、+d (C++) オプションを指定してコンパイルされたアプリケーションは通常よりも実行速度が遅くなります。+d オプションは C++ のインライン関数の拡張を禁止するため、各実行時の .d ファイルの更新にかなりの時間がかかります。


index.assist.d ファイルは、環境変数 TCOVDIR が指示するディレクトリに作成されます。TCOVDIR が設定されていない場合、index.assist.d はカレントディレクトリに作成されます。

index.assist.c のコンパイルが済んだら、index.assist を実行してください。


% index.assist 
% ls *.d
index.assist.d

それでは、tcov を実行して、プログラムの各ステートメントの実行カウントの集計結果が含まれるファイルを生成してください。tcovindex.assist.d ファイルを使って、コードの注釈リストを含む index.assist.tcov ファイルを生成します。この出力には、各ソースステートメントが実行された回数が示されます。ファイルの末尾には、短い要約が付いています。


% tcov index.assist.c 
% ls *.tcov
index.assist.tcov

次に、index.assist のモジュールの1つから、C コードの一部分 を示します。問題となっているモジュールは、呼び出し頻度の高い insert_index_entry 関数です。


        struct index_entry * 
11152->	insert_index_entry(node, entry) 
        structindex_entry *node; 
        struct index_entry *entry; 
        { 
            int result; 
            int level; 

            result = compare_entry(node, entry); 
            if (result == 0) { /* exact match */
                               /* Place the page entry for the duplicate */
                               /* into the list of pages for this node */ 
59  ->      insert_page_entry(node, entry->page_entry); 
            free(entry); 
            return(node); 
            } 

11093->     if (result > 0)  /* node greater than new entry -- */
                             /* move to lesser nodes */ 
3956->      if (node->lesser != NULL) 
3626->          insert_index_entry(node->lesser, entry); 
            else { 
330->       node->lesser = entry; 
            return (node->lesser); 
            } 
            else             /* node less than new entry -- */
                             /* move to greater nodes */ 
7137->      if (node->greater != NULL) 
6766->      insert_index_entry(node->greater, entry); 
            else { 
371->       node->greater = entry; 
            return (node->greater); 
            } 
        } 

C コードの左の数値は、各ステートメントが実行された回数を表しています。insert_index_entry 関数は 11,152 回呼び出されます。

tcov は、index.assist.tcov のファイルの末尾に以下のような集計情報を追加します。


           Top 10 Blocks 

         Line        Count 
         240         21563 
         241         21563 
         245         21563 
         251         21563 
         250         21400 
         244         21299 
         255         20612 
         257         16805 
         123         12021 
         124         11962 

77       Basic blocks in this file 
55       Basic blocks executed
71.43    Percent of the file executed

         439144    Total basic block executions
         5703.17   Average executions per basic block

コードカバレージ解析用にコンパイルされたプログラムは、(異なる入力を基にしての) 繰り返し実行が可能です。つまり、プログラムに対して tcov を繰り返し使用し、各実行時の動作を比較できるということです。

tcov によってプロファイル化された共有ライブラリの生成

tcov によってプロファイル化された共有ライブラリを生成し、バイナリファイルのリンクがすでに済んでいても、それを代わりに使用することが可能です。共有可能なライブラリを生成する場合は、-xa オプション (C) または -a オプション (その他のコンパイラ) を使用してください。以下に例を示します。


% cc -G -xa -o foo.so.1 foo.o

このコマンドは、共有可能なライブラリに tcov プロファイリングサブルーチンのコピーを組み込み、ライブラリのクライアントが再リンクしなくても済むようにします。ライブラリのクライアントもまたプロファイリング用にリンクされる場合、クライアントによって使用される tcov サブルーチンのバージョンは、共有可能ライブラリのプロファイルに使用されます。

ファイルのロック

tcov は、.d ファイルのブロックカバレージデータベースの更新に、シンプルなファイルロッキングメカニズムを使用します。tcov はこの目的のために単独ファイル /tmp/tcov.lock を使用します。そのため、システム上では、-xa (C) または -a (その他のコンパイラ) を使ってコンパイルされたただ 1 つの実行可能ファイルが実行されなければなりません。-xa または -a オプションを使ってコンパイルされたプログラムの実行は、手動で終了し、その後、/tmp/tcov.lock ファイルも手動で削除する必要があります。

プログラムが tcov によるプロファイリング用にリンクされると、-xa または -a オプションを使ってコンパイルされたファイルは自動的にプロファイリングツールのサブルーチンを呼び出します。プログラムの終了時点で、これらのサブルーチンは、ファイル xyz.f の実行時に収集された情報と、ファイル xyz.d に保存された既存のプロファイリング情報とを組み合わせます。プロファイル化されたバイナリファイルを同時に実行している人々にこの情報を変更されないようするため、更新期間中は xyz.d 用にロックファイル xyz.d.lock が作成されます。xyz.d またはそのロックファイルのオープンまたは読み取り時にエラーが存在する場合、あるいは、実行時の情報と保存されている情報との間に不整合が存在する場合、xyz.d に保存されているデータは更新されません。

xyz.d の編集または再コンパイルは、xyz.d のカウンタの数を変える可能性があります。古いプロファイル化されたバイナリの実行の際に、こうした変化が検出されます。

プロファイル化されたバイナリを実行する人が多すぎると、ロックが得られない可能性もあります。その場合は、数秒の遅れの後に、次のようなエラーメッセージが表示されます。

tcov_exit: Failed to create lock file '/tmp_mnt/net/rbbb/export/home/src/newpattern/foo.d.lock' for coverage data file '/tmp_mnt/net/rbbb/export/home/src/newpattern/foo.d' after 5 tries. Is somebody else running this binary?

そして、保存されている情報の更新は行われません。このロックはネットワークを通じて安全に機能します。ロックはファイル単位で行われるため、ほかのファイルは正しく更新されます。

プロファイリングサブルーチンは、アクセス不可能となっている自動マウントファイルシステムを処理しようと試みます。それでも、異なるマシン上で、カバレージデータファイルを含むファイルシステムに異なる名前がマウントされていたり、プロファイル化されたバイナリを実行するユーザーがカバレージデータファイルまたはそれを含むディレクトリに対する書き込み権を持っていない場合、この試みは失敗します。すべてのディレクトリには、統一化された名前を付け、バイナリを実行する可能性のあるユーザー誰もが書き込み可能な状態しておいてください。

tcov ランタイムによって報告されるエラー

以下のエラーメッセージが、tcov ランタイムルーチンによって報告されることがあります。

tcov_exit: Could not open coverage data file 'coverage data file name' because 'system error message string'.

このバイナリを実行するユーザーには、カバレージデータファイルに対する読み取り権および書き込み権がありません。カバレージデータファイルを含むディレクトリが削除されている場合も、こうした問題が起こります。

tcov_exit: Could not write coverage data file 'coverage data file name' because 'system error message string'.

このバイナリを実行するユーザーには、カバレージデータファイルを含むディレクトリに書き込み権がありません。カバレージデータファイルを含むディレクトリがバイナリを実行するマシンにマウントされていない場合も、こうした問題が起こります。


tcov_exit: Failed to create lock file 'lock file name' for coverage data file 'coverage data file name' after 5 tries. Is someone else running this executable?

多くのユーザーが同時にカバレージデータファイルを更新しようとしています。カバレージデータファイルが更新されている間に、マシンがクラッシュしたときも、ロックファイルが放置され、こうした問題は起こります。万一、クラッシュが起こった場合には、2 つのファイルのうちで長い方をクラッシュ後のカバレージデータファイルとして使用してください。ロックファイルは手動で削除してください。


tcov_exit: Stdio failure, probably no memory left.

利用可能なメモリがなく、標準 I/O パッケージが動作できません。この時点では、カバレージデータファイルの更新はできません。


tcov_exit: Coverage data file path name too long (length characters) 'coverage data file name'.

ロックファイル名は、カバレージデータファイル名にさらに 6 文字追加されます。そのため、派生ロックファイル名が規則違反となる可能性があります。


tcov_exit: Coverage data file 'coverage data file name' is too short. Is it out of date?

tcov プロファイル用のライブラリまたはバイナリが、同時に実行、編集、再コンパイルされようとしています。古いバイナリは一定サイズのカバレージデータファイルを予期しますが、編集によってそのサイズはしばしば変更されます。古いバイナリが古いカバレージデータファイルを更新しようとしているときに、コンパイラが新しいカバレージデータファイルを作成すると、バイナリファイルは空白、あるいは壊れた状態で表示されます。

tcov Enhanced − ステートメントレベルの解析

オリジナルの tcov 同様、tcov Enhanced は、プログラムの実行方法についての行単位の情報を提供します。tcov Enhanced は、どの行がどれくらいの頻度で使用されているかを示す注釈が付けられたソースファイルのコピーを作成します。また、基本ブロックに関する要約情報も提供します。tcov Enhanced は、C および C++ のソースファイルに対して動作します。

tcov Enhanced では、オリジナル tcov のいくつかの欠点が改善されています。

tcov Enhanced 用のコンパイル

tcov Enhanced を使用するには、オリジナルの tcov と同様の以下の手順に従ってください。

  1. tcov Enhanced の実験データ用にプログラムをコンパイルします。

  2. 実験を実行します。

  3. tcov を使って、結果を解析します。

オリジナルの tcov では、-xa オプションを使ってコンパイルを行いました。 tcov Enhanced によってコードカバレージ用のプログラムをコンパイルするには、すべてのコンパイラに対して、-xprofile=tcov オプションを使用してください。index.assist という名前のプログラムを例として使用する場合、tcov Enhanced を使ったコンパイルは以下のようなコマンドになります。

% cc -xprofile=tcov -o index.assist index.assist.c

tcov Enhanced は、tcov とは異なり、.d ファイルを作成しません。プログラムが実行されるまで、カバレージデータファイルは作成されません。カバレージ解析用にコンパイルされた各モジュールごとに 1 つのファイルではなくて、プログラム実行後に 1 つのカバレージデータファイルが作成されます。

index.assist.c のコンパイルの後、index.assist を実行して、プロファイルデータを生成してください。


% index.assist 
% ls -dF *.profile 
index.assist.profile/ 	
% ls *.profile 	
tcovd

デフォルトでは、tcovd ファイルが保存されるディレクトリの名前は、実行可能ファイルの名前から派生して付けられます。また、そのディレクトリは、実行可能ファイルが実行されたディレクトリに作成されます (オリジナルの tcov は、モジュールがコンパイルされたディレクトリに .d ファイルを作成します)。

tcovd ファイルが保存されるディレクトリはまた、「プロファイルバケット」 として知られます。プロファイルバケットは、環境変数 SUN_PROFDATA を使用することで、上書きできます。実行可能なファイル名が argv[0] の値と等しくない場合などに、この操作は有効です (たとえば、違う名前のシンボリックリンクから実行可能ファイルが実行された場合など)。

プロファイルバケットが生成されたディレクトリを上書きすることも可能です。実行ディレクトリとは別のディレクトリを指定するには、環境変数 SUN_PROFDATA_DIR を使ってパスを指定してください。この変数には、相対パス名、絶対パス名のどちらでも指定できます。相対パス名は、プログラムの実行完了時のカレントの作業ディレクトリに対する相対的な位置となります。

TCOVDIR は、SUN_PROFDATA_DIR の下方互換性を維持するために同類の環境変数としてサポートされています。SUN_PROFDATA_DIR が設定されている場合、TCOVDIR が無視されます。TCOVDIRSUN_PROFDATA_DIR の両者が設定されていると、プロファイルバケットが生成された時点で、警告が表示されます。SUN_PROFDATA_DIR は、TCOVDIR よりも優先されます。これらの変数は、-xprofile=tcov オプションによってコンパイルされたプログラムの実行時に使用され、さらに、tcov コマンドによって使用されます。


注 -

このスキーマはプロファイルフィードバックメカニズムによっても使用されます。


いくつかのカバレージデータが作成されたら、生データをソースファイルに関連付けるレポートを生成できます。


% tcov -x index.profile index.assist.c 
% ls *.tcov 
index.assist.c.tcov

このレポートの出力は、前の例 (オリジナルの tcov のもの) と同じです。

プロファイル化された共有ライブラリの生成

tcov Enhanced とともに使用するための共有ライブラリの生成は、以下の類似したコンパイルオプションを使って遂行できます。

% cc -G -xprofile=tcov -o foo.so.1 doo.o

ファイルのロック

tcov Enhanced は、ブロックカバレージデータファイルの更新にシンプルなファイルロッキングメカニズムを使用します。tcov Enhanced は、tcovd ファイルと同じディレクトリに生成された単独ファイルを使用します。そのファイル名は tcovd.temp.lock です。カバレージ解析用にコンパイルされたプログラムの実行が手動で終了された場合、ロックファイルは必ず手動で削除してください。

ロックの競合が存在する場合、このロッキングスキームは指数バックオフを行います。そして、5 回試みた後、tcov ランタイムがロックを獲得できないと、tcov はあきらめ、その実行用のデータは失われます。この場合、以下のメッセージが表示されます。

tcov_exit: temp file exists, is someone else running this executable?

tcov 用ディレクトリおよび環境変数

tcov 用にプログラムをコンパイルし、そのプログラムを実行すると、実行プログラムはプロファイルバケットを生成します。既にプロファイルバケットが存在している場合、プログラムはそのプロファイルバケットを使用します。プロファイルバケットが存在していない場合は、プロファイルバケットを生成します。

プロファイルバケットは、プロファイル出力が生成されるディレクトリを指定します。プロファイル出力の名前と場所は、環境変数で指定可能なデフォルトの設定によって制御されます。


注 -

tcov は、プロファイルフィードバックを集めるために使用したコンパイラオプション -xprofile=collect-xprofile=use によって使用される同じデフォルトと環境変数を使用します。これらのコンパイラオプションの詳細については、ご使用のコンパイラのマニュアルを参照してください。


プログラムが生成するデフォルトのプロファイルバケットの名前は、実行可能ファイル名 + .profile となり、実行可能ファイルが実行されるディレクトリに生成されます。そのため、カレントディレクトリが /home/joe で、/usr/bin/xyz というプログラムを実行すると、デフォルト動作としては、/home/joexyz.profile という名前のプロファイルバケットが生成されます。

デフォルトを変更するための環境変数を以下に示します。

実行時のプロファイルバケットの名前の指定に使用できます。この変数の値は、常に SUN_PROFDATA_DIR の値に追加されます (両方の変数が設定されている場合)。

プロファイルバケットを含むディレクトリの名前の指定に使用できます。これは実行時および tcov コマンドにおいて使用されます。

TCOVDIR は、下方互換性を維持するため、SUN_PROFDATA_DIR の同類の環境変数としてサポートされています。SUN_PROFDATA_DIR が設定されている場合、TCOVDIR は無視されます。TCOVDIRSUN_PROFDATA_DIR の両者が設定されていると、プロファイルバケットが生成された時点で、警告が表示されます。

TCOVDIR は、 -xprofile=tcov を使用してコンパイルされたプログラムの実行時にに使用され、さらに tcov コマンドによって使用されます。

デフォルト設定の無効化

デフォルトを上書きするには、環境変数を使用してプロファイルバケットを変更します。

  1. 環境変数 SUN_PROFDATA を使って、プロファイルバケットの名前を変更します。

  2. 環境変数 SUN_PROFDATA_DIR を使って、プロファイルバケットが置かれているディレクトリを変更します。

この 2 つの環境変数はプロファイルバケットのデフォルトの保存場所と名前を上書きします。保存場所と名前は別々に上書きすることができます。たとえば、SUN_PROFDATA_DIR の設定だけを選択すると、プロファイルバケットは SUN_PROFDATA_DIR に設定されたディレクトリに移動しますが、デフォルトの名前 (実行可能ファイル名 +.profile) が引き続きプロファイルバケット用の名前として使用されます。

絶対パス名と相対パス名

プロファイルフィードバック用のコンパイル行上では、SUN_PROFDATA_DIR によって、絶対パス名 (「/」から始まる) と相対パス名の 2 種類のディレクトリの形式を指定できます。絶対パス名を使用する場合、プロファイルバケットはそのディレクトリに収められます。一方、相対パス名を使用する場合、プロファイルバケットは実行可能ファイルが実行されるカレントの作業ディレクトリに対して相対的な位置関係になります。

たとえば、カレントディレクトリが /home/joe で、SUN_PROFDATA_DIR.. に設定された状態で /usr/bin/xyz というプログラムを実行すると、プロファイルバケットは /home/joe/../xyz.profile となります。環境変数に指定された値が相対的であるため、プロファイルバケットは /home/joe と相対的な位置関係となります。またこの例では、実行可能ファイル名を使用した、デフォルトのプロファイルバケット名が使用されます。

TCOVDIRSUN_PROFDATA_DIR

旧バージョンの tcov (-xa または -a フラグによるコンパイルによって使用可能となります) は、TCOVDIR という環境変数を使用していました。TCOVDIR は、ソースファイルと同じディレクトリではなく、tcov カウンタファイルが収められるディレクトリを指定しました。この環境変数との互換性を維持するため、新しい環境変数 SUN_PROFDATA_DIRTCOVDIR 環境変数と同様に動作します。両方の変数が設定されている場合、警告が出力され、SUN_PROFDATA_DIR が、TCOVDIR よりも優先されます。

-xprofile=tcov

デフォルトでは、プロファイルバケットは、カレントディレクトリにある <argv[0]>.profile と呼ばれます。

SUN_PROFDATA を設定している場合、プロファイルバケットは、どこに保存されていようと、$SUN_PROFDATA と呼ばれます。

SUN_PROFDATA_DIR を設定している場合、プロファイルバケットは、指定されたディレクトリに保存されます。

SUN_PROFDATASUN_PROFDATA_DIR はそれぞれ独立しています。いずれの環境変数も設定されていると、プロファイルバケット名は、SUN_PROFDATA_DIR を使ってプロファイルバケットを見つけ出すことによって生成され、SUN_PROFDATA はそのディレクトリのプロファイルバケットの命名に使用されます。

UNIX のプロセスでは、プログラム実行中、カレントの作業ディレクトリが変更されることがあります。そのため、プロファイルバケットの生成に使用されるカレントの作業ディレクトリは、プログラムの実行終了時におけるカレントの作業ディレクトリとなります。まれですがプログラムの実行中にそのカレント作業ディレクトリを変更するような場合には、環境変数を利用して、プロファイルバケットが生成される場所をコントロールしてください。

tcov プログラムについて

-xprofile=bucket オプションは、tcov プロファイル用に使用されるプロファイルバケットの名前を指定します。SUN_PROFDATA_DIR または TCOVDIR が設定されている場合、いずれか一方がこの引数に付加されます。