On 30.10.2010 00:47, Jeremy Bopp wrote:
> On 10/29/2010 5:36 PM, Ammar Ali wrote:
>> I see. I excluded the i += 1 from the for and times loops because that is
>> done automatically. Adding them seemed to add work that was not necessary
>> for those constructs, and IMHO, make the benchmark inaccurate.
>
> That's definitely a debatable point in this benchmark because we are
> essentially doubling the number of add operations for the loops that
> perform it implicitly.  However, we also want to see how the choice of
> looping mechanism affects the operations performed within the loop, so
> making the looped operations completely identical has its merits.

I'm sorry but this is nonsense: different loop constructs are 
benchmarked precisely to determine which iteration is quicker. 
Incrementing the loop variable is one of the things that make up the 
difference between looping constructs so there is no point in doing this 
"manually" just to make loop bodies look identical.

Here's my version

Robert@babelfish ~
$ ruby19 x.rb
Rehearsal ----------------------------------------------
for loop     2.168000   0.000000   2.168000 (  2.211000)
while loop   1.981000   0.000000   1.981000 (  2.015000)
times loop   2.075000   0.016000   2.091000 (  2.150000)
------------------------------------- total: 6.240000sec

                  user     system      total        real
for loop     2.106000   0.000000   2.106000 (  2.149000)
while loop   1.919000   0.000000   1.919000 (  1.919000)
times loop   2.012000   0.000000   2.012000 (  2.063000)


Robert@babelfish ~
$ cat x.rb
require 'benchmark'

count = 1_000_000

Benchmark.bmbm do |bm|
   bm.report("for loop") {
     5.times do
       for i in 0...count
         i * i
       end
     end
   }

   bm.report("while loop") {
     5.times do
       i = 0
       while i < count
         i * i
         i += 1
       end
     end
   }

   bm.report("times loop") {
     5.times do
       count.times do |i|
         i * i
       end
     end
   }
end

puts

> Regardless, the big thing we see is that the loops all perform roughly
> equivalently overall.  Their relative differences in overhead will
> likely be dwarfed by the looped operations in the real world.

Agreed.

> In this case, I would choose the more idiomatic approach for the sake of
> brevity, familiarity, and safety.  I really hate how easy it is to have
> off-by-one errors and similar problems in the more manually iterated for
> and while constructs.

Actually there was one in the first posting of this thread:

>     for i in 1..layers[0].count-1
>       puts i
>     end
>
> Is it equivalent in efficiency to this?
>
> int i = 1
> while i < layers[0].count-1
>    puts i
> i+=1
> end

The answer is no because the second one does one less iteration. :-)

Please note also that you can use three dot ranges to exclude the end so 
the first one could be rewritten as

for i in 1...layers[0].count
   # ...
end

Kind regards

	robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/