• 关于for,while,dowhile效率测试


    引言

      大家都知道每种循环对应的效率是不同的,书中都说在循环中使用减法的效率是比加法的效率高的,具体情况是怎么样,我们将详细列出各循环的执行效率问题。本文通过查看汇编代码比较各循环的效率以及i++,++i,i--,--i在循环中使用的效率问题,仅供抛砖引玉,测试平台为intel i5 4440,编译器为gcc-4.8.2

    测试代码1

      此段代码我们主要测试在i--,--i,i++,++i的情况下,for循环、dowhile循环、while循环之间的执行效率情况

     1 #include <stdio.h>
     2 
     3 /* 用于测试i--的while,for,dowhile循环情况 */
     4 void minus1 (void)
     5 {
     6     int i = 10;
     7 
     8     /* i-- while循环 */
     9     while (i--)
    10         ;
    11 
    12     i = 10;
    13 
    14     /* i-- dowhile循环 */
    15     do
    16         ;
    17     while (i--);
    18 
    19     /* i-- for循环 */
    20     for (i = 10; i != 0; i--)
    21         ;
    22 }
    23 
    24 /* 用于测试--i的while,for,dowhile循环情况 */
    25 void minus (void)
    26 {
    27     int i = 10;
    28 
    29     /* --i while循环 */
    30     while (--i)
    31         ;
    32 
    33     i = 10;
    34 
    35     /* --i dowhile循环 */
    36     do
    37         ;
    38     while (--i);
    39 
    40     /* --i for循环 */
    41     for (i = 10; i != 0; --i)
    42         ;
    43 }
    44 
    45 /* 用于测试i++的while,for,dowhile循环情况 */
    46 void plus1 (void)
    47 {
    48     int i = 0;
    49 
    50     /* i++ while循环 */
    51     while (i++ < 10)
    52         ;
    53 
    54     i = 0;
    55 
    56     /* i++ dowhile循环 */
    57     do
    58         ;
    59     while (i++ < 10);
    60 
    61     /* i++ for循环 */
    62     for (i = 0; i < 10; i++)
    63         ;
    64 }
    65 
    66 /* 用于测试++i的while,for,dowhile循环情况 */
    67 void plus (void)
    68 {
    69     int i = 0;
    70 
    71     /* ++i while循环 */
    72     while (++i < 10)
    73         ;
    74 
    75     i = 0;
    76 
    77     /* ++i dowhile循环 */
    78     do
    79         ;
    80     while (++i < 10);
    81 
    82     /* ++i for循环 */
    83     for (i = 0; i < 10; ++i)
    84         ;
    85 }
    86 
    87 
    88 int main (int argc, char * argv[])
    89 {
    90     return 0;
    91 }

    测试代码1所生成的汇编代码如下:

      1 #include <stdio.h>
      2 
      3 void minus1 (void)
      4 {
      5   4004ed:    55                       push   %rbp
      6   4004ee:    48 89 e5                 mov    %rsp,%rbp
      7     int i = 10;
      8   4004f1:    c7 45 fc 0a 00 00 00     movl   $0xa,-0x4(%rbp)         # i = 10
      9 
     10     while (i--)                                                        # while (i--)
     11   4004f8:    90                       nop                              # 空指令
     12   4004f9:    8b 45 fc                 mov    -0x4(%rbp),%eax            # eax = i                                     主循环
     13   4004fc:    8d 50 ff                 lea    -0x1(%rax),%edx            # edx = rax - 1(rax的低32位为eax)              主循环
     14   4004ff:    89 55 fc                 mov    %edx,-0x4(%rbp)            # i = edx                                     主循环
     15   400502:    85 c0                    test   %eax,%eax                  # 等同于(i & i), 如果i不等于0,则结果也不为0       主循环
     16   400504:    75 f3                    jne    4004f9 <minus1+0xc>        # 不等于0则跳转至4004f9                         主循环
     17         ;
     18 
     19     i = 10;
     20   400506:    c7 45 fc 0a 00 00 00     movl   $0xa,-0x4(%rbp)            # i = 10
     21 
     22     do
     23         ;
     24     while (i--);                                                        # do ... while (i--); 
     25   40050d:    8b 45 fc                 mov    -0x4(%rbp),%eax            # eax = i                                      主循环
     26   400510:    8d 50 ff                 lea    -0x1(%rax),%edx            # edx = rax - 1(rax的低32位为eax)               主循环
     27   400513:    89 55 fc                 mov    %edx,-0x4(%rbp)            # i = edx                                      主循环
     28   400516:    85 c0                    test   %eax,%eax                  # 等同于(i & i), 如果i不等于0,则结果也不为0        主循环
     29   400518:    75 f3                    jne    40050d <minus1+0x20>       # 不等于0则跳转至40050d                          主循环
     30 
     31     for (i = 10; i != 0; i--)                                           # for (i = 10; i != 0; i--)
     32   40051a:    c7 45 fc 0a 00 00 00     movl   $0xa,-0x4(%rbp)            # i = 10
     33   400521:    eb 04                    jmp    400527 <minus1+0x3a>       # 跳转至400527
     34   400523:    83 6d fc 01              subl   $0x1,-0x4(%rbp)            # i = i - 1                                    主循环
     35   400527:    83 7d fc 00              cmpl   $0x0,-0x4(%rbp)            # i与0进行比较                                 主循环
     36   40052b:    75 f6                    jne    400523 <minus1+0x36>       # 比较结果不等于0则跳转至400523                主循环
     37         ;
     38 }
     39 
     40 void minus (void)
     41 {
     42   40052f:    55                       push   %rbp
     43   400530:    48 89 e5                 mov    %rsp,%rbp
     44     int i = 10;
     45   400533:    c7 45 fc 0a 00 00 00     movl   $0xa,-0x4(%rbp)
     46 
     47     while (--i)                                                         # while (--i) 
     48   40053a:    83 6d fc 01              subl   $0x1,-0x4(%rbp)            # i = i - 1                        主循环
     49   40053e:    83 7d fc 00              cmpl   $0x0,-0x4(%rbp)            # i与0比较                         主循环
     50   400542:    75 f6                    jne    40053a <minus+0xb>         # 比较结果不等于0则跳转至40053a              主循环
     51         ;
     52 
     53     i = 10;
     54   400544:    c7 45 fc 0a 00 00 00     movl   $0xa,-0x4(%rbp)
     55 
     56     do
     57         ;
     58     while (--i);                                                        # do ... while (--i);
     59   40054b:    83 6d fc 01              subl   $0x1,-0x4(%rbp)            # i = i - 1                                 主循环
     60   40054f:    83 7d fc 00              cmpl   $0x0,-0x4(%rbp)            # i与0比较                                 主循环
     61   400553:    75 f6                    jne    40054b <minus+0x1c>        # 比较结果不等于0则跳转至40054b                 主循环
     62 
     63     for (i = 10; i != 0; --i)                                           # for (i = 10; i != 0; --i)
     64   400555:    c7 45 fc 0a 00 00 00     movl   $0xa,-0x4(%rbp)            # i = 10
     65   40055c:    eb 04                    jmp    400562 <minus+0x33>        # 跳转至400562
     66   40055e:    83 6d fc 01              subl   $0x1,-0x4(%rbp)            # i = i - 1                                主循环
     67   400562:    83 7d fc 00              cmpl   $0x0,-0x4(%rbp)            # i与0比较                                   主循环
     68   400566:    75 f6                    jne    40055e <minus+0x2f>        # 比较结果不等于0则跳转至40055e                 主循环
     69         ;
     70 }
     71 
     72 void plus1 (void)
     73 {
     74   40056a:    55                       push   %rbp
     75   40056b:    48 89 e5                 mov    %rsp,%rbp
     76     int i = 0;
     77   40056e:    c7 45 fc 00 00 00 00     movl   $0x0,-0x4(%rbp)
     78 
     79     while (i++ < 10)                                                    # while (i++ < 10)     
     80   400575:    90                       nop
     81   400576:    8b 45 fc                 mov    -0x4(%rbp),%eax            # eax = i                                 主循环
     82   400579:    8d 50 01                 lea    0x1(%rax),%edx             # edx = rax + 1(rax的低32位为eax)         主循环
     83   40057c:    89 55 fc                 mov    %edx,-0x4(%rbp)            # i = edx                                主循环
     84   40057f:    83 f8 09                 cmp    $0x9,%eax                  # eax与9比较                              主循环
     85   400582:    7e f2                    jle    400576 <plus1+0xc>         # 比较结果不成立则跳转至400576              主循环
     86         ;
     87 
     88     i = 0;
     89   400584:    c7 45 fc 00 00 00 00     movl   $0x0,-0x4(%rbp)
     90 
     91     do
     92         ;
     93     while (i++ < 10);                                                   # while (i++ < 10);
     94   40058b:    8b 45 fc                 mov    -0x4(%rbp),%eax            # eax = i                                    主循环 
     95   40058e:    8d 50 01                 lea    0x1(%rax),%edx             # edx = rax + 1(rax的低32位为eax)             主循环
     96   400591:    89 55 fc                 mov    %edx,-0x4(%rbp)            # i = edx                                    主循环
     97   400594:    83 f8 09                 cmp    $0x9,%eax                  # eax与9比较                                  主循环
     98   400597:    7e f2                    jle    40058b <plus1+0x21>        # 比较结果不成立则跳转至40058b                  主循环
     99 
    100     for (i = 0; i < 10; i++)                                            # for (i = 0; i < 10; i++)
    101   400599:    c7 45 fc 00 00 00 00     movl   $0x0,-0x4(%rbp)            # i = 0                                         
    102   4005a0:    eb 04                    jmp    4005a6 <plus1+0x3c>        # 跳转至4005a6                                     
    103   4005a2:    83 45 fc 01              addl   $0x1,-0x4(%rbp)            # i = i + 1                                  主循环
    104   4005a6:    83 7d fc 09              cmpl   $0x9,-0x4(%rbp)            # i与9比较                                    主循环
    105   4005aa:    7e f6                    jle    4005a2 <plus1+0x38>        # 比较结果不成立则跳转至4005a2                  主循环
    106         ;
    107 }
    108 
    109 void plus (void)
    110 {
    111   4005ae:    55                       push   %rbp
    112   4005af:    48 89 e5                 mov    %rsp,%rbp
    113     int i = 0;
    114   4005b2:    c7 45 fc 00 00 00 00     movl   $0x0,-0x4(%rbp)
    115 
    116     while (++i < 10)                                                    # while (++i < 10)
    117   4005b9:    83 45 fc 01              addl   $0x1,-0x4(%rbp)            # i = i + 1                                   主循环
    118   4005bd:    83 7d fc 09              cmpl   $0x9,-0x4(%rbp)            # i与9比较                                     主循环
    119   4005c1:    7e f6                    jle    4005b9 <plus+0xb>          # 比较结果不成立则跳转至4005b9                   主循环
    120         ;
    121 
    122     i = 0;
    123   4005c3:    c7 45 fc 00 00 00 00     movl   $0x0,-0x4(%rbp)
    124 
    125     do
    126         ;
    127     while (++i < 10);                                                   # while (++i < 10);
    128   4005ca:    83 45 fc 01              addl   $0x1,-0x4(%rbp)            # i = i + 1                                   主循环
    129   4005ce:    83 7d fc 09              cmpl   $0x9,-0x4(%rbp)            # i与9比较                                     主循环
    130   4005d2:    7e f6                    jle    4005ca <plus+0x1c>         # 比较结果不成立则跳转至4005b9                   主循环
    131 
    132     for (i = 0; i < 10; ++i)                                            # for (i = 0; i < 10; ++i)
    133   4005d4:    c7 45 fc 00 00 00 00     movl   $0x0,-0x4(%rbp)            # i = 0
    134   4005db:    eb 04                    jmp    4005e1 <plus+0x33>         # 跳转至4005e1
    135   4005dd:    83 45 fc 01              addl   $0x1,-0x4(%rbp)            # i = i + 1                                   主循环
    136   4005e1:    83 7d fc 09              cmpl   $0x9,-0x4(%rbp)            # i与9比较                                     主循环
    137   4005e5:    7e f6                    jle    4005dd <plus+0x2f>         # 比较结果不成立则跳转至4005dd                   主循环
    138         ;
    139 }

    可以从汇编代码得出如下表格

      while主循环语句数

    do...while主循环语句数

    for主循环语句数
    i-- 5 5 3
    --i 3 3 3
    i++ 5 5 3
    ++i 3 3 3

    小结

      可以从表中得出结论:循环效率最高也需要执行3条汇编语句,而最慢需要5条汇编语句,使用i--和i++进行循环控制时,不同的循环结构所对应的汇编代码量不同,最少的为for循环,只需要3条汇编指令,最多的为while循环,需要5条汇编指令,而当使用--i和++i进行循环控制时,无论哪一种循环结构执行效率都一样是最优的,都只需要3条代码,而无论使用i--,--i,i++,++i中哪一种,for循环的效率应该是最高的,都只用了3条汇编代码。

  • 相关阅读:
    Linux的中文输入法Fcitx-国货精品
    Linux内核编译与安装[转]
    Linux内核编译与安装[转]
    修改镜像地址加快Ubuntu更新速度
    修改镜像地址加快Ubuntu更新速度
    OSX操作技巧:快速锁定系统(类似Windows+L)
    NDK编程入门笔记[转]
    NDK编程入门笔记[转]
    内置函数图形分类
    函数的定义
  • 原文地址:https://www.cnblogs.com/tolimit/p/4236821.html
Copyright © 2020-2023  润新知