zoukankan      html  css  js  c++  java
  • switch与ifelse的效率问题

    转载:http://blog.csdn.net/kehui123/article/details/5298337

    switch与if..else 的执行的效率问题
    今天读一前辈的程序,发现其在串口中断里面为了分析协议的报文类型,在中断函数里面使用if..else语句。因为报文类型在现在看来只有两种,以后有可能还会增加,不确定。
    本人以为这样用有些不妥,为什么不用switch语句呢?猜想是不是因为效率方面的考虑呢,毕竟我们应该尽量是中断的处理代码更加简洁,时间效率更高才好。
    所以本人就查找相关资料,资料显示switch语句反而比ifelse的执行效率要高。
    下面来详细描述switch与ifelse的区别。
    switch...case与if...else的根本区别在于,switch...case会生成一个跳转表来指示实际的case分支的地址,而这个跳转表的索引号与switch变量的值是相等的。从而,switch...case不用像if...else那样遍历条件分支直到命中条件,而只需访问对应索引号的表项从而到达定位分支的目的。
    具体地说,switch...case会生成一份大小(表项数)为最大case常量+1的跳表,程序首先判断switch变量是否大于最大case 常量,若大于,则跳到default分支处理;否则取得索引号为switch变量大小的跳表项的地址(即跳表的起始地址+表项大小*索引号),程序接着跳到此地址执行,到此完成了分支的跳转。
    //

    int main()
    {
    unsigned int i,j;
    i=3;
    switch (i)
    {
      case 0:
      j=0;
      break;
      case 1:
      j=1;
      break;
      case 2:
      j=2;
      break;
      case 3:
      j=3;
      break;
      case 4:
      j=4;
      break;
      default:
      j=10;
      break;
    }

    }

    用gcc编译器,生成汇编代码(不开编译器优化)
    .file "shiyan.c"
    .text
    .globl main
    .type main, @function
    main:
    leal 4(%esp), %ecx
    andl $-16, %esp
    pushl -4(%ecx)
    pushl %ebp
    movl %esp, %ebp
    pushl %ecx
    subl $20, %esp
    movl $3, -8(%ebp)
    cmpl $4, -8(%ebp)
    ja .L2
    movl -8(%ebp), %eax
    sall $2, %eax
    movl .L8(%eax), %eax
    jmp *%eax
    .section .rodata
    .align 4
    .align 4
    .L8:
    .long .L3
    .long .L4
    .long .L5
    .long .L6
    .long .L7
    .text
    .L3:
    movl $0, -12(%ebp)
    jmp .L11
    .L4:
    movl $1, -12(%ebp)
    jmp .L11
    .L5:
    movl $2, -12(%ebp)
    jmp .L11
    .L6:
    movl $3, -12(%ebp)
    jmp .L11
    .L7:
    movl $4, -12(%ebp)
    jmp .L11
    .L2:
    movl $10, -12(%ebp)
    .L11:
    addl $20, %esp
    popl %ecx
    popl %ebp
    leal -4(%ecx), %esp
    ret
    .size main, .-main
    .ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section .note.GNU-stack,"",@progbits

    由此看来,switch有点以空间换时间的意思,而事实上也的确如此。
    1.当分支较多时,当时用switch的效率是很高的。因为switch是随机访问的,就是确定了选择值之后直接跳转到那个特定的分支,但是if。。else是遍历所以得可能值,知道找到符合条件的分支。如此看来,switch的效率确实比ifelse要高的多。
    2.由上面的汇编代码可知道,switch...case占用较多的代码空间,因为它要生成跳表,特别是当case常量分布范围很大但实际有效值又比较少的情况,switch...case的空间利用率将变得很低。
    3.switch...case只能处理case为常量的情况,对非常量的情况是无能为力的。例如 if (a > 1 && a < 100),是无法使用switch...case来处理的。所以,switch只能是在常量选择分支时比ifelse效率高,但是ifelse能应用于更多的场合,ifelse比较灵活。

    由此看来,上面前辈的中断处理程序中用switch是比较合适的,即节省了时间,而且对于以后程序的扩展也是很方便。因为报文类型这个值基本上都是用整形常量来表示的。

     

    -------------------------------------------------------------------------------------------------------------------------------------------

    下面的评论也很有货:

    switch也并不总是那么好,因为每次计算会有一个二次查表过程。
    具体需要看应用场景,举个例子:对于网络层的协议分析,%99可能都是IP协议,因此基本上会在第一个if时就命中,只有一次计算。
    更多的优化措施还有likely/unlikely。
    总结来说:对于分支较多或分布相对均匀的情况,使用switch可以提高效率;对于分支较少或分布不均匀的情况,使用if...if else更好。

     

    switch只能作用于那些同一类型的数值化选择,使用范围很窄;事实上if语句用的更多。
    究其原因就是很多连续判断的种类不一样,也无法数值化,故而根本不能用switch。
    就比如写一个键盘按钮与鼠标都可以对屏幕进行移动的操作,LZ可以写出switch的判断吗??当然,你可以先if下到底是键盘事件还是鼠标事件再来用switch。

     

     

    自己总结:

    如果在要比较的情况单一的情况下(并且匹配较分散的情况,排除5楼)可以使用switch

    如果在要比较的情况比较多(如两个符合语句,或者5楼)则使用if    if…else 结构

  • 相关阅读:
    jMeter 里 CSV Data Set Config Sharing Mode 的含义详解
    如何使用 jMeter Parallel Controller
    使用 Chrome 开发者工具 coverage 功能分析 web 应用的渲染阻止资源的执行分布情况
    使用 Chrome 开发者工具的 lighthouse 功能分析 web 应用的性能问题
    关于 SAP 电商云首页加载时触发的 OCC API 请求
    SAP UI5 确保控件 id 全局唯一的实现方法
    SAP 电商云 Accelerator 和 Spartacus UI 的工作机制差异
    介绍一个好用的能让网页变成黑色背景的护眼 Chrome 扩展应用
    Chrome 开发者工具 performance 标签页的用法
    Client Side Cache 和 Server Side Cache 的区别
  • 原文地址:https://www.cnblogs.com/0xcafedaddy/p/5095567.html
Copyright © 2011-2022 走看看