而(1) for(;;)有速度差吗? [英] while (1) Vs. for (;;) Is there a speed difference?

查看:105
本文介绍了而(1) for(;;)有速度差吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

长版本...



一位同事今天在看到我使用后宣称,<1> for(;;)的Perl脚本中更快。我认为他们应该是一样的,希望翻译将优化任何差异。我设置一个脚本,将运行1,000,000,000循环迭代和相同数量的while循环,并记录之间的时间。我找不到明显的区别。我的同事说,一个教授告诉他 while(1)正在做一个比较 1 == 1 for(;;)不是。我们用100倍的C ++迭代次数重复了同样的测试,差别可以忽略不计。然而,它是一个图形化的例子,表明编译代码与脚本语言相比有多快。



短版本...



有任何理由喜欢 while(1)超过为(;;) if你需要一个无限循环来打破?



注意:如果从问题中不清楚。这是纯粹是一个有趣的学术讨论之间的几个朋友。我知道这不是一个超级重要的概念,所有的程序员都应该痛苦。感谢所有伟大的答案,我(我相信其他人)从这次讨论中学到了一些东西。



更新:



此处引用以防万一。


它来自AMD组装程序员。他说C程序员
(这个人)没有意识到他们的代码没有效率。他说
今天,gcc编译器是非常好的,并把人们喜欢他出来
的业务。他说,例如,告诉我关于 while 1 vs
for(;;)。我现在使用它现在离开习惯,但gcc,特别是翻译
将做同样的操作(处理器跳转)这两天,
,因为他们被优化。


< block perl,它们导致相同的操作码:

 >  $ perl -MO = Concise -e'for(;;){printfoo\\\
}'
a< @> leave [1 ref] vKP / REFC - >(end)
1< 0> enter - > 2
2< ;;> nextstate(main 2 -e:1)v - > 3
9 2 leaveloop vK / 2 - > a
3< {> enterloop(next-> 8 last-> 9 redo-> 4)v - > 4
- < @> lineseq vK - > 9
4< ;;> nextstate(main 1 -e:1)v - > 5
7< @> print vK - > 8
5< 0> pushmark s - > 6
6< $> const [PVfoo \\\
] s - > 7
8< 0> unstack v - > 4
-e语法OK

$ perl -MO = Concise -e'while(1){printfoo\\\
}'
a< ; @> leave [1 ref] vKP / REFC - >(end)
1< 0> enter - > 2
2< ;;> nextstate(main 2 -e:1)v - > 3
9 2 leaveloop vK / 2 - > a
3< {> enterloop(next-> 8 last-> 9 redo-> 4)v - > 4
- < @> lineseq vK - > 9
4< ;;> nextstate(main 1 -e:1)v - > 5
7< @> print vK - > 8
5< 0> pushmark s - > 6
6< $> const [PVfoo \\\
] s - > 7
8< unstack v - > 4
-e语法OK

同样在GCC中:

  #include< stdio.h> 

void t_while(){
while(1)
printf(foo\\\
);
}

void t_for(){
for(;;)
printf(foo\\\
);
}

.filetest.c
.section .rodata
.LC0:
.stringfoo
.text
.globl t_while
.type t_while,@function
t_while:
.LFB2:
pushq%rbp
.LCFI0:
movq% rsp,%rbp
.LCFI1:
.L2:
movl $ .LC0,%edi
call puts
jmp .L2
.LFE2:
.size t_while,。-t_while
.globl t_for
.type t_for,@function
t_for:
.LFB3:
pushq%rbp $ b b .LCFI2:
movq%rsp,%rbp
.LCFI3:
.L5:
movl $ .LC0,%edi
调用puts
jmp .L5
.LFE3:
.size t_for ,.-t_for
.section .eh_frame,a,@ progbits
.Lframe1:
.long .LECIE1 -.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.stringzR
.uleb128 0x1
.sleb128 -8
.byte 0x10
.uleb128 0x1
.byte 0x3
.byte 0xc
.uleb128 0x7
.uleb128 0x8
.byte 0x90
.uleb128 0x1
.align 8
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long。 LASFDE1-.Lframe1
.long .LFB2
.long .LFE2-.LFB2
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB2
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI1-.LCFI0
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE1:
.LSFDE3:
.long .LEFDE3-.LASFDE3
.LASFDE3:
.long.LASFDE3-.Lframe1
.long .LFB3
.long .LFE3-.LFB3
.uleb128 0x0
.byte 0x4
.long .LCFI2- .LFB3
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI3-.LCFI2
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE3:
.identGCC:(Ubuntu 4.3.3-5ubuntu4)4.3.3
.section .note.GNU-stack,,@ progbits

所以我想答案是,它们在许多编译器中是相同的。当然,对于一些其他编译器,这可能不一定是这样,但是机会是循环中的代码将比循环本身贵几千倍,所以谁关心?


Long version...

A co-worker asserted today after seeing my use of while (1) in a Perl script that for (;;) is faster. I argued that they should be the same hoping that the interpreter would optimize out any differences. I set up a script that would run 1,000,000,000 for loop iterations and the same number of while loops and record the time between. I could find no appreciable difference. My co-worker said that a professor had told him that the while (1) was doing a comparison 1 == 1 and the for (;;) was not. We repeated the same test with the 100x the number of iterations with C++ and the difference was negligible. It was however a graphic example of how much faster compiled code can be vs. a scripting language.

Short version...

Is there any reason to prefer a while (1) over a for (;;) if you need an infinite loop to break out of?

Note: If it's not clear from the question. This was purely a fun academic discussion between a couple of friends. I am aware this is not a super important concept that all programmers should agonize over. Thanks for all the great answers I (and I'm sure others) have learned a few things from this discussion.

Update: The aforementioned co-worker weighed in with a response below.

Quoted here in case it gets buried.

It came from an AMD assembly programmer. He stated that C programmers (the poeple) don't realize that their code has inefficiencies. He said today though, gcc compilers are very good, and put people like him out of business. He said for example, and told me about the while 1 vs for(;;). I use it now out of habit but gcc and especially interpreters will do the same operation (a processor jump) for both these days, since they are optimized.

解决方案

In perl, they result in the same opcodes:

$ perl -MO=Concise -e 'for(;;) { print "foo\n" }'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v ->3
9     <2> leaveloop vK/2 ->a
3        <{> enterloop(next->8 last->9 redo->4) v ->4
-        <@> lineseq vK ->9
4           <;> nextstate(main 1 -e:1) v ->5
7           <@> print vK ->8
5              <0> pushmark s ->6
6              <$> const[PV "foo\n"] s ->7
8           <0> unstack v ->4
-e syntax OK

$ perl -MO=Concise -e 'while(1) { print "foo\n" }'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 2 -e:1) v ->3
9     <2> leaveloop vK/2 ->a
3        <{> enterloop(next->8 last->9 redo->4) v ->4
-        <@> lineseq vK ->9
4           <;> nextstate(main 1 -e:1) v ->5
7           <@> print vK ->8
5              <0> pushmark s ->6
6              <$> const[PV "foo\n"] s ->7
8           <0> unstack v ->4
-e syntax OK

Likewise in GCC:

#include <stdio.h>

void t_while() {
    while(1)
    	printf("foo\n");
}

void t_for() {
    for(;;)
    	printf("foo\n");
}

    .file   "test.c"
    .section    .rodata
.LC0:
    .string "foo"
    .text
.globl t_while
    .type   t_while, @function
t_while:
.LFB2:
    pushq   %rbp
.LCFI0:
    movq    %rsp, %rbp
.LCFI1:
.L2:
    movl    $.LC0, %edi
    call    puts
    jmp .L2
.LFE2:
    .size   t_while, .-t_while
.globl t_for
    .type   t_for, @function
t_for:
.LFB3:
    pushq   %rbp
.LCFI2:
    movq    %rsp, %rbp
.LCFI3:
.L5:
    movl    $.LC0, %edi
    call    puts
    jmp .L5
.LFE3:
    .size   t_for, .-t_for
    .section    .eh_frame,"a",@progbits
.Lframe1:
    .long   .LECIE1-.LSCIE1
.LSCIE1:
    .long   0x0
    .byte   0x1
    .string "zR"
    .uleb128 0x1
    .sleb128 -8
    .byte   0x10
    .uleb128 0x1
    .byte   0x3
    .byte   0xc
    .uleb128 0x7
    .uleb128 0x8
    .byte   0x90
    .uleb128 0x1
    .align 8
.LECIE1:
.LSFDE1:
    .long   .LEFDE1-.LASFDE1
.LASFDE1:
    .long   .LASFDE1-.Lframe1
    .long   .LFB2
    .long   .LFE2-.LFB2
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI0-.LFB2
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI1-.LCFI0
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE1:
.LSFDE3:
    .long   .LEFDE3-.LASFDE3
.LASFDE3:
    .long   .LASFDE3-.Lframe1
    .long   .LFB3
    .long   .LFE3-.LFB3
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI2-.LFB3
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI3-.LCFI2
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE3:
    .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section    .note.GNU-stack,"",@progbits

So I guess the answer is, they're the same in many compilers. Of course, for some other compilers this may not necessarily be the case, but chances are the code inside of the loop is going to be a few thousand times more expensive than the loop itself anyway, so who cares?

这篇关于而(1) for(;;)有速度差吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆