RubySpeed

From APIDesign

Jump to: navigation, search

Ruby was always known to be very slow language. Even when the hype around Rails was on - e.g. around 2006, there was nobody who could make the language fast. The great news is that OracleLabs decided to demonstrate the power of their Truffle framework on Ruby and are working on a fast Ruby implementation. OracleLabs claim that their implementation is ten times faster than the standard Ruby.

I wanted to verify such claim. One thing is being faster in a benchmark, the other thing is to speed up real programs. That is why I decided to write my first Ruby program - the Sieve of Eratosthenes and as following video demonstrates, Truffle based Ruby is really faster:

Is Truffle based Ruby ten times faster? The video shows that standard Ruby can compute about 5000 of prime numbers in 20s on my computer. The Truffle version was able to compute 17000 of primes. For a while I believed that this implies three times speed up. Not bad, but far less than the claim of being ten times faster.

However once, while showing the demo, I forgot to kill the standard Ruby version. After three minutes I noticed that and to my surprise the standard version was still fighting with 15000th prime number - e.g. it takes at least 180s to compute what Truffle Ruby can in 20s. The explanation is easy - computing first thousands of primes is way easier that finding the next thousands ones. The sieve of Eratosthenes algorithm isn't linear. Only comparing the time to compute the same amount of primes makes sense. However such time comparison actually shows ten times speed up!

class Natural
  def initialize
    @x = 2
  end
 
  def next
    return @x += 1
  end
end
natural = Natural.new
 
class Filter
  def initialize(number, filter)
    @number = number
    @filter = filter
  end
 
  def number
    @number
  end
 
  def filter
    @filter
  end
 
  def accept(n)
    filter = self
    loop do
      if (n % filter.number) == 0
        return false
      end
      filter = filter.filter;
      break if filter == nil
    end
    return true;
  end
end
 
class Primes
  def initialize(natural)
    @natural = natural
    @filter = nil;
  end
 
  def next
    loop do
      n = @natural.next
      if (@filter == nil || @filter.accept(n))
        @filter = Filter.new(n, @filter)
        return n;
      end
    end
  end
end
primes = Primes.new(natural)
 
puts "Press Ctrl-D to start..."
$stdin.read
 
start = Time.now
cnt = 0
res = ""
puts "Working..."
loop do
  p = primes.next
  res << "#{p}\n"
  cnt += 1
  if cnt % 1000 == 0
    puts res
    puts "Computed #{cnt} primes in #{Time.now - start} s"
    res = ""
  end
end


Truffle gives Ruby the speed it always needed.

Personal tools
buy