On 02/05/2010 07:36 PM, Aaron Gifford wrote:
> What's the fastest way to iterate over a range in variable increments?
> 
> For example, using irb (1.9.1):
> 
> irb(main):001:0>
> a=0;s=Time.now;i=0;while(i<1000000000);a+=i;i+=5;end;e=Time.now;p
> e-s;p a
> 8.715433734
> 99999999500000000
> => 99999999500000000
> irb(main):002:0>
> a=0;s=Time.now;Range.new(0,1000000000,true).step(5){|i|a+=i};e=Time.now;p
> e-s;p a
> 18.932204045
> 99999999500000000
> => 99999999500000000
> 
> As you can see I'm stepping by 5 over the range 0 to 1000000000
> exclusive (excluding the last item) doing a simple operation each
> iteration (the operation above is totally contrived).
> 
> In this case, it appears that while outperforms Range's step method.

robert@fussel:~$ ruby19 xx.rb
Rehearsal --------------------------------------------------
while           15.650000   0.030000  15.680000 ( 17.892211)
range step      33.650000   0.070000  33.720000 ( 38.560748)
step            30.680000   0.110000  30.790000 ( 34.767791)
---------------------------------------- total: 80.190000sec

                      user     system      total        real
while           15.700000   0.050000  15.750000 ( 18.651631)
range step      33.690000   0.060000  33.750000 ( 38.554879)
step            30.660000   0.100000  30.760000 ( 35.095686)
robert@fussel:~$ cat xx.rb

require 'benchmark'

LI = 1000000000
ST = 5

Benchmark.bmbm 15 do |b|
   b.report "while" do
     i = 0
     while i < LI
       i += ST
     end
   end

   b.report "range step" do |b|
     (0...LI).step ST do
     end
   end

   b.report "step" do |b|
     0.step LI, ST do
     end
   end
end
robert@fussel:~$

I think we are seeing an effect of the missing call to the block that 
happens on each iteration for #step approaches.  The while loop does not 
have this overhead.

Kind regards

	robert

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