代码改变世界

关于for,while,dowhile效率测试

2015-01-22 11:03  tolimit  阅读(4958)  评论(1编辑  收藏  举报

引言

  大家都知道每种循环对应的效率是不同的,书中都说在循环中使用减法的效率是比加法的效率高的,具体情况是怎么样,我们将详细列出各循环的执行效率问题。本文通过查看汇编代码比较各循环的效率以及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条汇编代码。