http://www.perlmonks.org?node_id=136238


in reply to do/redo or for(;;): what's Kosher?

Some say for(;;) is inefficient, because it's a C-style loop.
Some say {; redo;} is inefficient, because it won't let perl optimize.
Some say while(1) is inefficient, because the 1 has to be evaluated over and oer.

I wanted to know, so I benchmarked. I found it somewhat hard to benchmark infinite loops, so I made them finite with a nice closure construct.

#!/usr/bin/perl -w use strict; use Benchmark; sub ender () { my $i = 0; return sub { ++$i == 10000 } } Benchmark::cmpthese(-5, { 'for (;;)' => sub { my $end = ender(); for (;;) { last if $end->() } }, 'while (1)' => sub { my $end = ender(); while (1) { last if $end->() } }, '{; redo;}' => sub { my $end = ender(); { last if $end->(); redo; } } }); __END__ Benchmark: running for (;;), while (1), {; redo;}, each for at least 5 CPU seconds... for (;;): 9 wsecs (5.48 usr + 0.01 sys = 5.49 CPU) @ 57.56/s (n=316) while (1): 8 wsecs (5.26 usr + 0.01 sys = 5.27 CPU) @ 60.34/s (n=318) {; redo;}: 8 wsecs (5.08 usr + 0.00 sys = 5.08 CPU) @ 57.68/s (n=293) Rate for (;;) {; redo;} while (1) for (;;) 57.6/s -- -0% -5% {; redo;} 57.7/s 0% -- -4% while (1) 60.3/s 5% 5% --


I've tried this many times. while seems to be the winner.

Update (200201041112+0100)
This is really odd. I've run the benchmark above about a hundred times now, and while won almost every one of them.

BUT
2;1 juerd@ouranos:~$ perl -MO=Deparse -e'while (1) { print "1\n" }' for (;;) { print "1\n"; } -e syntax OK 2;0 juerd@ouranos:~$ perl -MO=Deparse -e'for (;;) { print "1\n" }' for (;;) { print "1\n"; } -e syntax OK

Can anyone explain this?

2;0 juerd@ouranos:~$ perl -e'undef christmas' Segmentation fault 2;139 juerd@ouranos:~$

Replies are listed 'Best First'.
Re: Re: do/redo or for(;;): what's Kosher?
by robin (Chaplain) on Jan 04, 2002 at 20:02 UTC
    The constructs for (;;), while (1), and until (0) all generate exactly the same opcodes. If one is consistently faster than the other, that might perhaps tell you more about your benchmarking procedure than about the code you're trying to benchmark. :-) I tried running your code with the time limit increased from 5 CPU seconds to 60 CPU seconds, and got:
    Rate {; redo;} while (1) for (;;) {; redo;} 17.7/s -- -4% -5% while (1) 18.5/s 4% -- -0% for (;;) 18.5/s 5% 0% --
    suggesting that while and for are the same speed after all, which is something of a relief.