C++ 调用空类方法是否会影响性能?
计时器.h:C++ 调用空类方法是否会影响性能?,c++,performance,visual-studio-2005,C++,Performance,Visual Studio 2005,计时器.h: class Timer { public: void start(); void printTimeAndRestart(const char* msg); }; namespace Timing { static Timer timer; } class Timer { public: void start(); void printTimeAndRestart(const char* msg); }; namespace Timing { stati
class Timer
{
public:
void start();
void printTimeAndRestart(const char* msg);
};
namespace Timing { static Timer timer; }
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) { ... };
#else
//empty - do not do timing
void Timer::start() {};
void Timer::printTimeAndRestart(const char* /*msg*/) {};
#endif
#ifdef DO_TIMING
//implementation
void Timer::start() { ... };
void Timer::printTimeAndRestart(const char* msg) { ... };
#endif
计时器将用于许多不同的文件,如:
Timing::timer.start();
...
Timing::timer.printTimeAndRestart("Operation X took :");
若应用程序对性能非常敏感,并且经常调用计时器,那个么在并没有定义时间的情况下调用空方法会影响性能吗?实现独立计时器(无需重新编译整个项目来打开/关闭)的更好选项是什么?关闭时,它根本不会影响性能
到目前为止,我只想到定义宏,比如
#ifdef DO_TIMING
#define START_TIMING()
Timing::timer.start();
#endif
#else
#define START_TIMING()
#endif
并使用它们而不是计时::timer.start();但这将需要重新编译整个代码来打开/关闭它们…在调试构建中,这将被调用,并将具有任何函数调用的总体效果。在优化代码中,编译器通常会忽略调用 根据下面的评论
在调用站点,编译器将无法确定被调用函数是否无效。如果宏也内联定义了空条件,那么调用站点将能够看到函数本质上是一个noop。这取决于您如何使用它。如果它是同一个项目/解决方案,并且编译器能够进行完整的程序优化,那么它可能与此无关
如果您正在分发带有二进制文件的代码,并且实现不可见,并且编译器无法判断代码是否为空,则调用将产生一些(较小的)开销。如果您希望编译器更确定地优化调用,请执行以下操作: 计时器.h:
class Timer
{
public:
void start();
void printTimeAndRestart(const char* msg);
};
namespace Timing { static Timer timer; }
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) { ... };
#else
//empty - do not do timing
void Timer::start() {};
void Timer::printTimeAndRestart(const char* /*msg*/) {};
#endif
#ifdef DO_TIMING
//implementation
void Timer::start() { ... };
void Timer::printTimeAndRestart(const char* msg) { ... };
#endif
高质量的编译器可能会将其删除,但更安全的做法是确保空函数内联在.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
不幸的是,这确实意味着您将依赖项绑定到头文件中,这将导致在打开或关闭时重新编译。如果函数定义为“内联”(即,作为声明它们所属类的头文件的一部分),则编译器可以避免为空函数生成代码。如果函数位于.cpp文件中,编译器必须生成调用函数的代码,因为编译器无法知道函数的功能[除非编译器支持“全程序优化”]
我的解决方案是将函数移到头文件中,而不是使用宏。这是一个更简洁的解决方案,除非编译器完全是垃圾,否则它应该把它归类为“没有生成代码” 编译器如何能够省略调用?定义不在同一个TU中,我不会假设LTO。它可以确定任何空函数都没有效果,因此不调用它。这类似于编译器在优化时如何将函数优化为内联。但在编译调用所在的文件时,它无法知道函数没有任何效果,因为它看不到其定义或任何东西。这一点很好。整个程序优化将能够实现。或配置文件引导。但更好的是,它应该是内联定义的,而不是没有效果。还没有-在上面所写的实现过程中,但我发布了一些帖子,看看还有哪些其他设计选项/是否有可能通过查看desingYep立即判断性能是否会受到影响…这将增加更多确定性(对于确定性的某些定义). 尽管当在代码库中任意添加一个
#define
可能会破坏这样的东西时,我会感到不安。(无可否认,提问者发明了#define
)