Ruby 1.9 doesn't smoke Python away!

November 28, 2007 [last comment: December 26, 2007]

In his blog entry "Holy Shmoly, Ruby 1.9 smokes Python away!" Antonio proposed following Python benchmarks for calculating first 36 Fibonacci numbers.

def fib(n):
    if n == 0 or n == 1:
        return n
    else:
        return fib(n-1) + fib(n-2)

for i in range(36):
    print "n=%d => %d" % (i, fib(i))

Antonio noticed that on his workstation above code was executed for 31.507s and analog in Ruby 1.9 – 11.934s. On my 4-years old workstation same code took 60.656s, but what time we will see if same 36 Fibonacci numbers with we will find with Python generators?

def fib(n):
    a, b = 0, 1
    i = 0
    while i < n:
        yield (i, a)
        a, b = b, a + b
        i += 1

for i, f in fib(36):
    print "n=%d => %d" % (i, f)

Well, my old workstation shown me for above code 0.078s, so almost in 1000 times faster (and please note 0.078s include time for reading and parsing python source by python interpreter).

As Antonio wrote: Now it’ll be very interesting to run a series of algorithmically equivalent tests for Ruby and Python, and to see just when exactly Ruby 1.9 manages to knock Python out of the water – and where Python has still the edge.

And it's hard to disagree with Antonio, it's really interesting to see where Ruby manages to knock Python out of the water.

P.S. In the memory of Java, which was my favorite language before Python, I made same Fibonacci test on same workstation and it was executed for 0.808s. Not so bad, by the way, but it's so hard code in Java after Python.

class fib {
    public static int fib(int n) {
        if (n == 0 || n == 1)
            return n;
        return (fib(n-1) + fib(n-2));
    }

    public static void main(String[] args) {
        for (int i = 0; i < 36; i++)
            System.out.println("n=" + i + " => " + fib(i));
    }
}

Tags: django  performance  tips 
Submitted 25 comments: accepted - 25, in moderation queue - 0.
  • Python Guy on November 28, 2007
    Hah.
  • Eugene on November 28, 2007
    Well, if all programmers wrote such code with generators then python software would be faster. But the original program is the one that will be probably written by average developer. So one needs to think different (c) IBM :)
  • Anonymous on November 28, 2007
    This is not fair since the algorithm was changed from being recursive to being iterative. You can do the same in ruby:

    def fib (n, &block)
    a, b = 0, 1
    i = 0
    while i #{f}" }

    time that one to make the comparison fair.
  • Anonymous on November 28, 2007
    Oh and fix your blog comments to support pasting code :)

    def fib (n, &block)
    a, b = 0, 1
    i = 0
    while i < n
    yield [i, a]
    a, b = b, a + b
    i += 1
    end
    end

    fib(36) { |i, f| puts "n=#{i} => #{f}" }
  • rcoder on November 28, 2007
    Oh, c'mon Anonymous, if you're going to bait the Pythonistas, you may as well go all the way and embrace everything that makes Ruby syntax truly different from Python:

    fib = lambda {|n,b| i,k=0,1; n.times {|p| b[p, i]; i,k=k,i+k } }
    fib[36, proc {|i, f| puts "n=%d => %d" % [i, f] }]

    ...which runs in about 1/2 the time of the Python generator-based solution above on my workstation.

    To be fair, the difference is much smaller when you increase the number of iterations to 1000 or so, which suggests to me that the overhead of launching the interpreter is probably the biggest use of time in these trivial examples.
  • John on November 28, 2007
    Is anyone actually saying they would switch or choose either language based on how long something takes to run? If that were the case, Java would have never been successful.
  • anonymous on November 28, 2007
    crap. full of shit article. I code in machine language 0 and 1, beat that!
  • Nick on November 28, 2007
    anonymous, please post us your version of Fibonacci numbers in 0 and 1.. Oh, I forgot, please write it in fifteen minutes :)
  • micasa on November 28, 2007
    You are cheating, man. Do you think we are stupid?
  • Dima Dogadaylo on November 28, 2007
    micasa, I'm not cheating, I just wanted to show that same problem can be resolved more or less effectively in the borders of same language. For example, I added P.S. section to the article with implementation of same Fibonacci "benchmark" in Java. Well, Java recursions runs in dozens of times faster than both Python and Ruby recursions, but Python generators overact even Java recursions, so what is faster Python or Java?

    For the real performance much more important developers skills than programming language benchmarks.
  • Daniel on November 28, 2007
    As long as you're cheating, how about this in ruby, which runs in 0.01s on my machine:

    @cache = []

    def fib(n)
    return @cache[n] if @cache[n]
    return n if n < 2
    return @cache[n] = fib(n-1) + fib(n-2)
    end

    36.times {|n| puts "fib(#{n}) = #{fib(n)}" }

    Or, how about this one-liner that runs is 0.008 seconds:

    @c=[]; def f(n) if !@c[n]; return n if n<2; return @c[n]=f(n-1)+f(n-2) end; @c[n] end; 1.upto(36) {|n| puts f(n)}
  • esauro on November 29, 2007
    In fact ruby and python are both good language. They are not focus in perfomance but in developer happiness. Both can do console, desktop and web application with low efforts.

    IMHO this language war lead to great language improve to beat the other therefore is great!!! but you can choose whether python or ruby and solve most of your projects using them. I'd much rather python than ruby but this is my personal view. There is no objective reason.
  • jinzo on November 29, 2007
    yay, and let the yet another epic war to begin.
  • Aivo on November 29, 2007
    Its not the tool its how you use it !
    So quit dick measurement contest and get laid or something.
  • dp_wiz on November 29, 2007
    Yeah, Ruby fans. But the "fast" code looks perlish "explosion at ASCII factory" q:
  • Anonymous on November 30, 2007
    Memoization. Do you have it?
  • ADA on November 30, 2007
    >> Yeah, Ruby fans. But the "fast" code looks perlish "explosion at ASCII factory" q:

    ROTFL! so true
  • Anonymous on November 30, 2007
    oohh noez

    someones suggested that my favorite language {ruby || python || java || c# } isn't the {best || fastest || coolest } in some arbitrary code examplez

    I mustz run to itz defenze

    sigh....

    on a related note - oh look I just deleted another site from my RSS reader for being lame.
  • AkitaOnRails on November 30, 2007
    My friend Rodrigo Kochenburger (http://blog.divoxx.com) suggested another way that's even faster:

    http://pastie.caboo.se/123814

    In my Macbook time goes down to 0.004
  • AkitaOnRails on November 30, 2007
    I just made a Java 1.5 version: http://pastie.caboo.se/123847

    At just 36 times Ruby blows Java away, of course. The JVM startup alone kills the test, but for 10.000 times speed catches up and Java and Ruby ends up having roughly the same performance.
  • Shadowfiend on November 30, 2007
    Most of these points aren't really of any use, of course. If you read the original post, you'll see that the interest in the improved performance numbers is that it means improved method dispatch speeds, which is very important in a language as through-and-through OO as Ruby is. Switching it to an iterative algorithm is not checking the same thing. Similarly, comparing with Java isn't really useful because this is method dispatch in an interpreted language.

    And it bears mentioning that to me the most important note in that post was that Ruby 1.9 is doing so much better than Ruby 1.8. Python's performance is less important.
  • Jerry Heiselman on December 01, 2007
    I personally believe that the language war is stupid. Both languages are great and I believe that both should continue to compete and grow. In the end, it is going to be personal preference that decides which language you like better (I like the syntax and structure of Python over Ruby, but that isn't to say that I dislike Ruby). They have both managed to solve bringing OO-Programming to the mainstream, having features like reflection available, and guiding people to more secure, stable code. Python's guiding principal has never been speed, though efforts continue to improve in that area. Ruby seems to follow Perl's approach in that there is more than one way to do something (which some people love).

    I guess what I'm trying to say is, we should continue to compare and contrast the two languages so that they can both get better and stop bickering when one happens to do better at "X" than the other one.

    BTW, code speed / stability is 90% developer skill, not language features. They are all too close to compare based on that any longer.
  • hohonuuli on December 03, 2007
    "I personally believe that the language war is stupid. Both languages are great and I believe that both should continue to compete and grow."

    +1
  • Vesely Skalpirator on December 06, 2007
    Nu ty tormoz. Delo ne v "reshenii problemy", a v ispytanii detalej realizacii.
    Esli uzh na to poshlo, davaj zapolnim massiv vychislennymi rezul'tatami fib[0..100] i proga budet voobwe superbystroj. CHto jeto dokazyvaet? CHto Dima ne ponimaet smysla.
  • dagbrown on December 26, 2007
    Wow, you totally missed the point of the Ruby guy's test. He deliberately used a lame algorithm in order to stress the recursion and method-calling parts of the Ruby interpreter--areas of known weakness in the past.

    Then he tried the same deliberately-lame algorithm in Python, to see how well it did checking the same things. The benchmark isn't for how fast he can generate Fibonacci numbers (he's not that stupid)--it's for how fast the new Ruby can call methods and handle its stack.
Web log, research lab and soft parade of Dima Dogadaylo.
Email: entropyhacker at gmail dot com