Ruby 1.9 performance

This is just some quickie about the performance of Ruby1.9. I’m currently playing arround with visual pattern recognition (e.g. interpreting a barcode on a scanned page). As I do dislike the JAI and love the Ruby language (it’s all about the programmers happiness) it was an easy decision which language to use.

But analyzing a (roughly) 2000×3000 matrix, which is 6 million elements, is a computationally expensive task. Especially when doing stuff like matrix convolving operations or even just simple neighbourhood based decisions. So there is no question that threading has to be used, especially when running on a multi-core machine.

And this is where the problems start. Ruby (1.8) uses so called green threads which do not map to native threads but are controlled by the interpreter. So the application won’t scale over multiple cores. Furthermore, the MRI (Matz Ruby Interpreter) is not really slow, but also not really fast.
Ruby 1.9 comes to change those restraints. First of all threads are now native threads (even though being slowed down by the way they’re implemented), and secondly the code is now executed by something called YARV (Yet Another Ruby VM), which is indeed a bytecode based virtual machine. That massive architectural change improves the average speed of Ruby by roughly 1.5 (according to Matz).

My experience is that when doing simple list operations it’s way faster. When I ran my filter program which, includes a threshold and neighbourhood based average filter (and is spread over 18 threads), I was almost shocked by the performance improvement. Lets just see the numbers. They tell more than a thousend words:

Ruby 1.8:

real 163m48.059s user 158m57.742s sys 1m40.306s
Ruby 1.9:

real 11m7.155s user 9m44.076s sys 0m16.309s

So all in all Ruby 1.9 is roughly 16 times faster than 1.8 on this application (16.3296249118265 times to be exact).

2 Responses to “Ruby 1.9 performance”

  1. Marco Maniscalco says:

    Nice report! Would also be very interesting how the performance compares to Java 1.6!

    One question ;-) How did you realize the multithreading? Do all threats access the same matrix or ist this a copy held by each thread? Could be challanging, when implementing FFT distributed on different threads because one iteration depends on previous iterations an hereby on the current state of the matrix. (-> continuity)

  2. Christian says:

    Thanks :-)

    Each thread gets its very own matrix to work on as the image is split into each tile and each tile is handled by one thread. A better approch (which is to be implemented) would be to do the filtering as one step (but in a multithreaded way) and reduce the amount of data afterwards (to the interessting part which is only the “barcode”).
    This should work as the main motivation for using threads here is to share the load between the cores of my machine. But unfortunately even Ruby 1.9 does not really support this.

    Comparing the program to a version written in Java 1.6 indeed would be very interessting, but I just don’t like the JAI API :-)

Leave a Reply

Fork me on GitHub