1

私は現在、プロファイリングシステムをアプリケーションに実装しています。

コンパイラフラグ(NDEBUG)に基づいて定義された2つのマクロ関数があります。NDEBUGが定義されていない場合、これら2つの関数(profilingStart / profilingEnd)は、profilingStartが呼び出された時間とprofilingEndが呼び出された時間を示すプロファイリングレポートを生成します。

懸念されるのは、不一致が発生する可能性です。つまり、profilingStartが呼び出されたが、profilingEndが呼び出されなかった(またはその逆の)シナリオです。私のコードは実行時にこれらの状況をすでに認識していますが、この不一致が原因でコンパイル時にエラーが発生した場合は望ましいでしょう。

1つの提案は、do {...} while();を使用することです。プロファイリング関数が適切にペアになっていることを確認するために構築します。startマクロ関数にはdo{が含まれ、endマクロには} while()が含まれます。1つが欠落していると、コンパイル時にエラーが発生します。ただし、これにはいくつかの問題があります。profilingStart()およびprofilingEnd()呼び出しは、関数内で使用するとローカル変数のスコープに影響を与える可能性があるため、プロファイルされている関数の開始と終了でのみ使用できます( do {...} while()呼び出しが原因でスコープ外になる可能性があるため)。

私が持っていたもう1つのアイデアは、profilingStart関数で変数を宣言してから、profilingEnd関数でその変数の内容を変更しようとすることです。これにより、スコープの問題が回避され、変数が宣言されていない場合はコンパイラエラーが生成されます。ただし、end関数で変数の内容が変更されていることを確認する方法はありません。これは、profilingEnd関数の呼び出しを検証しないため、問題の半分にしか役立ちません。

いつものように、どんなコメントでも大歓迎です。前もって感謝します。

編集:範囲に関する私のコメントに関していくつかの混乱があるかもしれません。profilingStart()とprofilingEnd()は、常に同じ関数内で呼び出されます。関数の最初/最後で呼び出されない場合があります。これが私が意味したことの例です:

int DoSomething(void)
{
   profilingStart();
   int a;
   DoMath(a);
   profilingStop();
   return a; // a is out of scope here, as the do{...}while(0) construct has gone out of scope
}
4

3 に答える 3

3

C++ では、1 つの解決策は "RAII" イディオムを使用することです。このようなもの:

class Profiler {
  public:
    Profiler() { profilingStart(); }
    ~Profiler() { profilingEnd(); }
}

次に、次のように使用します。

{ // start of block you want to profile
    Profiler prof;
    ...
}

これprofilingEndにより、例外、早期リターンbreakなどがある場合でも が呼び出されることが保証されます。つまり、呼び出しがペアになっていることが絶対に保証されます。

ただし、プロファイリングするコードをブロックに入れる必要があります。

[編集]

profilingEndとは別のブロックに入れることができるようにしたいのを逃しましたprofilingStart

これに対処する方法については、以下の @Roddy のコメントを参照してください。たとえば、オブジェクトが破棄されるまでにプロファイラーが停止していることを確認するためにデストラクタをチェックさせることによって。これはコンパイル時には問題をキャッチしませんが、実行時には問題の「近く」で問題をキャッチします。

于 2011-07-06T19:36:13.730 に答える
0

コンストラクタでプロファイル イベントを開始し、デストラクタで終了するオブジェクトを作成してから、scoped_lock と同様のクラスを使用して、開始が常にペアになっていることを確認できます。そして、任意のスコープを作成できるので、どこでもこれを行うことができます

于 2011-07-06T19:36:55.427 に答える
0

尋ねられた質問については、@Nemoの回答をお勧めします。C++ の機能を使用してデストラクタを呼び出し、基本的なレキシカル スコープに固執します。

実行時間の測定には独自の有用性があることを認識していただければ幸いですが、これは「ボトルネック」を見つけるための非常に間接的な方法です。(私は「時間の浪費」の方が好きです。プログラムが遅いのは、場所が狭いからではなく、必要以上のことを無計画に行うから遅いのです。)

ここで、問題についてもう少し詳しく説明します。

于 2011-07-06T21:39:50.727 に答える