2017-08-16 181 views
2

我试图比较switch语句和查找表的性能,如下所示。C++:Switch语句与查找表的性能

这是使用switch语句的代码

#include <stdio.h> 

int main() 
{ 
    int n = 3; 

    for (long i = 0; i < 10000000; ++i) { 
     switch (n) { 
     case 0: 
      printf("Alpha"); 
      break; 
     case 1: 
      printf("Beta"); 
      break; 
     case 2: 
      printf("Gamma"); 
      break; 
     case 3: 
      printf("Delta"); 
      break; 
     default: 
      break; 
     } 
    } 

    return 0; 
} 

,这里是使用查找表的代码:

#include <stdio.h> 

static char const * const Greek[4] = { 
    "Alpha", 
    "Beta", 
    "Gamma", 
    "Delta" 
}; 

int main() 
{ 
    int n = 3; 

    for (long i = 0; i < 10000000; ++i) { 
     if (n >= 0 && n < 4) { 
      printf(Greek[n]); 
     } 
    } 

    return 0; 
} 

我运行在Ubuntu 14.04两个编程,gcc版本4.8.4,使用PERF版本4.4.13来分析性能。而结果是:

  • 开关声明:6.764077822秒
  • 的查找表:6.665140483秒

我不知道为什么switch语句比查找表的运行速度较慢。正如我所知道的,使用跳转表的切换语句,我认为它应该比我的程序中的查找表运行得更快(它有额外的if语句)。

+7

您的计时包括对'printf'的调用,这可能会导致结果不准确。 – Jonas

+4

你应该看看生成的汇编代码。 –

+5

,如果你打开了优化,'switch'和'if'将被一个优化的编译器优化掉。 – geza

回答

8

如果您正在编译优化,您的代码没有开关,也没有查找表。我只是一个for循环,使用相同的固定字符串多次调用printf()。任何最低限度合理的编译器实际上都会检测到n = 3永远不会被更改并优化它。也许你可以在循环中添加一个n = rand() % 4;

另一方面,如果您没有通过优化进行编译,那么采用时间就没有意义。

回想你的问题,我期望查询表比switch语句更快,因为switch语句将完全颠覆分支预测,而if将是没有问题的,总是如此。

+0

我使用默认选项gcc版本4.8.4。我会尝试没有优化编译器。 – tuanpm

+6

@tuanpm不!正如我所说,时间未优化的代码是没有意义的!它会告诉你什么都没有。 –

0

您的基准测试完全不足以衡量switch/lookup-table性能:几乎所有的时间都是在printf()调用中花费的。如果switch/lookup-table差异有任何影响,则由于整个运行时间较长,所以它会因测量噪声而变得相形见绌。


仅供参考:我希望在热的紧密循环中查表只需要大约十个时钟周期。在2 GHz CPU上,对于所有10000000次迭代(粗略估计,很容易出错两倍,但不影响整体评估),这仅为0.05秒。这是您的总运行时间的1%的订单!