【发布时间】:2012-06-02 06:18:33
【问题描述】:
我编写了以下程序来测试我的机器上虚拟功能的成本:
#include <iostream>
#include <ctime>
#define NUM_ITER 10000000000
// 5 seconds = 1000000000
static volatile int global_a;
void spin()
{
int a = global_a;
int b = a*a;
int c = a+5;
int d = a^b^c;
global_a = b*d;
}
struct A {
virtual void a() = 0;
};
struct B : A {
virtual void a() { spin(); }
};
struct C : A {
virtual void a() { spin(); }
};
void run_A1(A* a)
{
a->a();
}
void run_A(A* a)
{
for (long long i = 0; i < NUM_ITER; i++) {
run_A1(a);
}
}
void run()
{
for (long long i = 0; i < NUM_ITER; i++) {
spin();
}
}
int main()
{
global_a = 2;
A* a1 = new B;
A* a2 = new C;
std::clock_t c_begin, c_end;
c_begin = std::clock();
run_A(a1);
c_end = std::clock();
std::cout << "Virtual | CPU time used: "
<< 1000.0 * (c_end-c_begin) / CLOCKS_PER_SEC
<< " ms\n";
c_begin = std::clock();
run_A(a2);
c_end = std::clock();
std::cout << "Virtual | CPU time used: "
<< 1000.0 * (c_end-c_begin) / CLOCKS_PER_SEC
<< " ms\n";
c_begin = std::clock();
run();
c_end = std::clock();
std::cout << "Normal | CPU time used: "
<< 1000.0 * (c_end-c_begin) / CLOCKS_PER_SEC
<< " ms\n";
delete a1;
delete a2;
}
结果与我的预期相反:虚函数始终更快。例如,这是我使用NUM_ITER = 10000000000 得到的输出之一:
Virtual | CPU time used: 49600 ms
Virtual | CPU time used: 50270 ms
Normal | CPU time used: 52890 ms
通过对生成的汇编文件的分析,我可以确认编译器没有优化出任何重要的东西。我使用 GCC-4.7 和以下选项:
g++ -O3 -std=c++11 -save-temps -masm=intel -g0 -fno-exceptions -fno-inline test.cc -o test
为什么虚函数调用更快?或者为什么非虚拟函数调用更慢?分支预测器变得这么好了吗?或者也许它只是我的机器。也许有人也可以测试并发布他的时间安排?
【问题讨论】:
-
我无法在 ideone 上重现此内容。
-
MSVS 对于非虚拟呼叫也显示出明显的优势。
-
@Pubby:Ideone 不是测试这一点的最佳选择,因为他们一次在服务器上运行许多程序。
-
@jons34yp 你错了。拨打
sleep(1)加上几个clock()电话,您会发现很多事情都会使clock()判断的时间无效。 -
好吧,这并不能解释一切,因为这只是意味着
spin()可以内联,而虚拟方法不能。但是即使没有内联,非虚拟版本也应该更快。尝试先运行普通版本而不是最后运行。
标签: c++ performance virtual-functions