Stu wrote in post #1132125:

You have to back it up with proper benchmarks. A screenshot would even

be

better. Make sure you run it twice to enable proper caching and which

proper synthetic benchmarks generally do as the system may actually be

doing something else at the time. It’s not a bad idea to read about

finite

state machines and automata theory as well as the substitution model

before

you hit the philosophical “why doesn’t X language use Y semantics”

without

actual proof. While your benching don’t forget to add a proper recursion

example. It would be a shame not to hit every way we can transverse and

build new structures with our data.

Here is sample code that illustrates different loop performance.

class Integer

def soe0

# enhanced classical brute-force Sieve of Eratosthenes (SoE)

lndx = (self-1)>>1; sieve = Array.new(lndx,true)

0.step((Math.sqrt(self).to_i-3)/2) do |i|

next unless sieve[i]

((i*(i+3)*2)+3).step(lndx, (i*2)+3) { |j| sieve[j] = nil }

end

return [2] if self < 3

primes=[2]; 0.step(lndx) { |k| primes << (k*2)+3 if sieve[k] }

primes

end

def soe1

# enhanced classical brute-force Sieve of Eratosthenes (SoE)

lndx = (self-1)>>1; sieve = Array.new(lndx,true)

0.step((Math.sqrt(self).to_i-3)/2) do |i|

next unless sieve[i]

psn = ((i*(i+3)*2)+3); prmstep = (i*2)+3

while psn < lndx; sieve[psn]=nil; psn += prmstep end

end

return [2] if self < 3

primes=[2]; 0.step(lndx) { |k| primes << (k*2)+3 if sieve[k] }

primes

end

def soe2

# enhanced classical brute-force Sieve of Eratosthenes (SoE)

lndx = (self-1)>>1; sieve = Array.new(lndx,true)

0.step((Math.sqrt(self).to_i-3)/2) do |i|

next unless sieve[i]

psn = ((i*(i+3)*2)+3); prmstep = (i*2)+3

while psn < lndx; sieve[psn]=nil; psn += prmstep end

end

return [2] if self < 3

primes=[2]; k=0

while k < lndx; primes << (k*2)+3 if sieve[k]; k+=1 end

primes

end

def soe3

# enhanced classical brute-force Sieve of Eratosthenes (SoE)

lndx = (self-1)>>1; sieve = Array.new(lndx,true); i=0

while i < (Math.sqrt(self).to_i-3)/2

if sieve[i]

psn = ((i*(i+3)*2)+3); prmstep = (i*2)+3

while psn < lndx; sieve[psn]=nil; psn += prmstep end

end

i +=1

end

return [2] if self < 3

primes=[2]; k=0

while k < lndx; primes << (k*2)+3 if sieve[k]; k+=1 end

primes

end

end

require ‘benchmark’

limit= 50_000_001

Benchmark.bm(30) do |t|

puts “comparison of soe using Step and While loops”

t.report(“soe with 3 Step & 0 While loops”) do ret0 = limit.soe0 end

t.report(“soe with 2 Step & 1 While loops”) do ret1 = limit.soe1 end

t.report(“soe with 1 Step & 2 While loops”) do ret2 = limit.soe2 end

t.report(“soe with 0 Step & 3 While loops”) do ret3 = limit.soe3 end

end

System:

Lenovo V570 laptop, I5 2.3 GHz, 6 GB, PCLOS Linux kernel 3.4.72

Here are results from a typical run on Ruby-2.1.0p0.

Sometimes the last example is a little bit less/greater than the 3rd.

So converting the main loop to a While inside a While has least affect.

Rubinius 2.2.2 and JRuby 1.7.9 give different results

2.1.0p0 :007 > load ‘Primes/soe.rb’

user system total

real

comparison of soe using Step and While loops

soe with 3 Step & 0 While loops 6.740000 0.100000 6.840000 (6.936593)

soe with 2 Step & 1 While loops 4.770000 0.070000 4.840000 (4.915530)

soe with 1 Step & 2 While loops 4.100000 0.030000 4.130000 (4.190563)

soe with 0 Step & 3 While loops 4.190000 0.080000 4.270000 (4.365184)