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, (i2)+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 = (i2)+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 = (i2)+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 = (i2)+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)