2

Timer.h:

class Timer
{
public:
void start();
void printTimeAndRestart(const char* msg);
};
namespace Timing {    static Timer timer; }

Timer.cpp:

#ifdef DO_TIMING
//implementation
void Timer::start() { ... };
void Timer::printTimeAndRestart(const char* msg) { ... };
#else
//empty - do not do timing
void Timer::start() {};
void Timer::printTimeAndRestart(const char* /*msg*/) {};
#endif

タイマーは、次のようなさまざまなファイルで使用されます。

Timing::timer.start(); 
... 
Timing::timer.printTimeAndRestart("Operation X took :");

アプリケーションが非常にパフォーマンスに敏感で、タイマーが頻繁に呼び出される場合、DO_TIMINGが定義されていないときに空のメソッドを呼び出すと、パフォーマンスに影響しますか?分離されたタイマーを実装するためのより良いオプションは何でしょうか(オン/オフするためにプロジェクト全体を再コンパイルする必要はありません)。これは、オフのときにパフォーマンスにまったく影響しません。

これまでのところ、次のようなマクロの定義しか考えられません。

#ifdef DO_TIMING 
#define START_TIMING()
Timing::timer.start(); 
#endif
#else
#define START_TIMING()
#endif

そして、Timing :: timer.start();の代わりにそれらを使用します。しかし、それはそれらをオン/オフにするためにコード全体を再コンパイルする必要があります...

4

5 に答える 5

3

それはあなたがそれをどのように使うかに依存します。それが同じプロジェクト/ソリューションであり、コンパイラが完全なプログラム最適化を実行できる場合、それはおそらく無関係です。

バイナリを使用してコードを配布していて、実装が表示されておらず、コンパイラがコードが空であると判断できない場合は、呼び出しによって多少の(マイナーな)オーバーヘッドが発生します。

于 2013-03-21T15:59:27.173 に答える
0

デバッグビルドでは、これが呼び出され、関数呼び出しの全体的な効果があります。一般に、最適化されたコードでは、コンパイラーは呼び出しを省略します。

以下のコメントによると。

呼び出しサイトでは、コンパイラーは、呼び出された関数が効果がないことを判別できません。マクロで空の条件もインラインで定義されている場合、呼び出しサイトは関数が本質的にnoopであることを確認できます。

于 2013-03-21T15:57:18.027 に答える
0

コンパイラが呼び出しを最適化することをより確実にしたい場合は、次のようにします。

Timer.h:

class Timer
{
  public:
  void start();
  void printTimeAndRestart(const char* msg);
};

namespace Timing {    static Timer timer; }

#ifndef DO_TIMING
inline void Timer::start() {}
inline void printTimeAndRestart(const char*) {}
#endif

Timer.cpp:

#ifdef DO_TIMING
//implementation
void Timer::start() { ... };
void Timer::printTimeAndRestart(const char* msg) { ... };
#endif
于 2013-03-21T16:00:32.030 に答える
0

高品質のコンパイラはおそらくそれを削除しますが、空の関数が.hファイルにインライン化されていることを確認する方が安全です。

Timer.h

class Timer
{
public:
  void start();
  void printTimeAndRestart(const char* msg);
};

#ifndef DO_TIMING

inline void Timer::start() {}
inline void printTimeAndRestart(const char* msg) {}

#endif

namespace Timing {    static Timer timer; }

Timer.cpp

#ifdef DO_TIMING

// ...

#endif

残念ながら、これは、依存関係をヘッダーに結び付けていることを意味します。これにより、ヘッダーがオンまたはオフに切り替えられたときに再コンパイルが発生します。

于 2013-03-21T16:01:01.170 に答える
0

関数が「インライン」で定義されている場合(つまり、関数が属するクラスを宣言するヘッダーファイルの一部として)、コンパイラーは空の関数のコードの生成を回避できます。関数が.cppファイルにある場合、コンパイラは関数が何をするかを知ることができないため、関数を呼び出すためのコードを生成する必要があります[コンパイラが「プログラム全体の最適化」をサポートしない限り]。

私の解決策は、マクロを使用するのではなく、関数をヘッダーファイルに移動することです。これは優れたソリューションであり、コンパイラーが完全にゴミでない限り、「コードは生成されない」と分類する必要があります。

于 2013-03-21T16:01:54.487 に答える