tags:

views:

166

answers:

5

I have all kind of scripting with Ruby:

rails (symfony)
ruby (php, bash)
rb-appscript (applescript)

Is it possible to replace low level languages with Ruby too?

I write in Ruby and it converts it to java, c++ or c.

Cause People say that when it comes to more performance critical tasks in Ruby, you could extend it with C. But the word extend means that you write C files that you just call in your Ruby code. I wonder, could I instead use Ruby and convert it to C source code which will be compiled to machine code. Then I could "extend" it with C but in Ruby code.

That is what this post is about. Write everything in Ruby but get the performance of C (or Java).

The second advantage is that you don't have to learn other languages.

Just like HipHop for PHP.

Are there implementations for this?

+4  A: 

"Low level" is highly subjective. Many people draw the line differently, so for the sake of this argument, I'm just going to assume you mean compiling Ruby down to an intermediate form which can then be turned into machine code for your particular platform. I.e., compiling ruby to C or LLVM IR, or something of that nature.

The short answer is yes this is possible.

The longer answer goes something like this:

Several languages (Objective-C most notably) exist as a thin layer over other languages. ObjC syntax is really just a loose wrapper around the objc_*() libobjc runtime calls, for all practical purposes.

Knowing this, then what does the compiler do? Well, it basically works as any C compiler would, but also takes the objc-specific stuff, and generates the appropriate C function calls to interact with the objc runtime.

A ruby compiler could be implemented in similar terms.

It should also be noted however, that just by converting one language to a lower level form does not mean that language is instantly going to perform better, though it does not mean it will perform worse either. You really have to ask yourself why you're wanting to do it, and if that is a good reason.

jer
@jer. People say that when it comes to more performance critical tasks in Ruby, you could extend it with C. But the word extend means that you write C files that you just call in your Ruby code. I wonder, could I instead use Ruby and convert it to C source code which will be compiled to machine code. Then I could "extend" it with C but in Ruby code. That is what this post is about. Write everything in Ruby but get the performance of C (or Java).
never_had_a_name
@ajsie: A (any) compiler needs to be **extremely** clever to yield code anywhere as efficient as an extension written in [target language] right away (by a good [target language] programmer). C/C++ compilers are very clever these days, so they beat 90% of all assembly programmers in 90% of the cases, but they had centuries and backing from many big companies to get this far. But any Ruby->C compiler an open source group might be able to produce within 10 years will still be behind well-written C.
delnan
@ajsie: What you're saying by "extend" in the first context is what we language folk tend to call "bind". Also, "extend" in the second instance is known as "FFI". Ruby does provide bindings, but no FFI built in (however there are libraries for that), which will let you interact with C code.
jer
@jer: I'm too tired to double-check right now (it's almost 4:00am here in Germany, and I just got home from a gruesome 8h shift), but I think that as of Ruby 1.9.2, FFI is part of the standard library.
Jörg W Mittag
@Jörg: That could very well be, to be honest, I haven't paid much attention to the 1.9 branch yet. Ruby isn't a primary language I develop in anymore, so sometimes its hard to find the time to keep up with new developments.
jer
ajsie: If it was easy to convert Ruby to C and get significant performance improvement, you wouldn't need to, because the Ruby people would have already done that in the normal runtime. The reason it gets faster is because the semantics of C are very different: fixints with overflow, no exceptions, function calls fixed at compile-time, etc. Manual conversion to C works because it forces the programmer to make huge simplifying assumptions which aren't expressible in Ruby syntax.
Ken
+3  A: 

There is http://rubyforge.org/projects/ruby2c/ Ruby To C compiler. It actually only takes in a subset of Ruby though. I believe the main missing part is the Meta Programming features

Earlz
Is it a converter from Ruby to C and then it compiles the C source code to binary?
never_had_a_name
+3  A: 

There is also JRuby, if you still consider Java a low level language. Actually, the language itself has little to do here: it is possible to compile to JVM bytecode, which is independent of the language.

Chubas
Will this solve the performance issue people are addressing "you could extend Ruby with C/Java"?
never_had_a_name
You're not exending here (not adding functionality in those languages to your existing Ruby code), but rather running your code in a different virtual machine. And yes, JRuby is said to run faster than MRI, the virtual machine for ruby 1.8.~). However, there are some other implementations for the Ruby VM, and 1.9.1 promises to be faster. I have not benchmarked myself, but you can search for some comparison on speed for different Ruby implementations. JRuby is one of the fastest.
Chubas
+4  A: 

Such a compiler is an enormous piece of work. And even if it works, it still has to carry the ruby runtime and standard library (which wasn't built for performance but for usability) around, allow metaprogramming, do dynamic dispatch, etc - all these inflict tremendous runtime penalties, because a C compiler can neither understand nor optimize such abstractions. Ruby and other dynamic languages are not only slower because they are interpreted (or compiled to bytecode which is then interpreted), but also because they are, well, dynamic.

Example: A method call in C++ can be inlined in most cases, because the compiler knows the exact type of this (and if a subtype is passed, the method still can't change unless it is virtual, in which case a still very efficient lookup table is used). But in Ruby, classes and methods can change in any way at any time, thus a (relatively expensive) lookup is required every time. Languages like Ruby, Python or Perl have many features that simply are expensive, and most if not all relevant programs rely heavily on these features (of course, they are extremely useful!), so they cannot be removed or inlined. Simply put: Dynamic languages are very hard to optimize, simply doing what an interpreter would do and compiling that to machine code doesn't cut it. It's possible to get incredible speed out of dynamic languages, as e.g. V8 proofes, but you have to throw huge piles of money and offices full of clever programmers at it.

delnan
+2  A: 

Performance doesn't come solely from "low level" compiled languages. Cross-compiling your Ruby program to convoluted, automatically generated C code isn't going to help either. This will likely just confuse things, include long compile times, etc. And there are much better ways.

But you first say "low level languages" and then mention Java. Java is not a low-level language. It's just one step below Ruby in terms of high- or low-level languages. But if you look at how Java works, the JVM, bytecode and just-in-time compilation, you can see how high level languages can be fast(er). Ruby is currently doing something similar. MRI 1.8 was an interpreted language, and had some performance problems. 1.9 is much faster, it's using a bytecode interpreter. I'm not sure if it'll ever happen on MRI, but Ruby is just one step away from JIT on MRI.

I'm not sure about the technologies behind jRuby and IronRuby, but they may already be doing this. However, both have their own advantages and disadvantages. I tend to stick with MRI, it's fast enough and it works just fine.

AboutRuby