Just for the fun of it, here is a parallel Ruby version.
require 'benchmark'
num = ARGV[0].to_i
def is_prime?(n)
(2...n).all?{|m| n%m != 0 }
end
def sexy_primes_default(x)
(9..x).map do |i|
[i-6, i]
end.select do |j|
j.all?{|j| is_prime? j}
end
end
def sexy_primes_threads(x)
partition = (9..x).map do |i|
[i-6, i]
end.group_by do |x|
x[0].to_s[-1]
end
threads = Array.new
partition.each_key do |k|
threads << Thread.new do
partition[k].select do |j|
j.all?{|j| is_prime? j}
end
end
end
threads.each {|t| t.join}
threads.map{|t| t.value}.reject{|x| x.empty?}
end
puts "Running up to num #{num}"
Benchmark.bm(10) do |x|
x.report("default") {a = sexy_primes_default(num)}
x.report("threads") {a = sexy_primes_threads(num)}
end
On my 1.8GHz Core i5 MacBook Air, the performance results are:
# Ruby 1.9.3
$ ./sexyprimes.rb 100000
Running up to num 100000
user system total real
default 68.840000 0.060000 68.900000 ( 68.922703)
threads 71.730000 0.090000 71.820000 ( 71.847346)
# JRuby 1.6.7.2 on JVM 1.7.0_05
$ jruby --1.9 --server sexyprimes.rb 100000
Running up to num 100000
user system total real
default 56.709000 0.000000 56.709000 ( 56.708000)
threads 36.396000 0.000000 36.396000 ( 36.396000)
# JRuby 1.7.0.preview1 on JVM 1.7.0_05
$ jruby --server sexyprimes.rb 100000
Running up to num 100000
user system total real
default 52.640000 0.270000 52.910000 ( 51.393000)
threads 105.700000 0.290000 105.990000 ( 30.298000)
It looks like the JVM's JIT is giving Ruby a nice performance boost in the default case, while true multithreading helps JRuby perform 50% faster in the threaded case. What's more interesting is that JRuby 1.7 improves the JRuby 1.6 score by a healthy 17%!