Welcome Waxy.org and Slashdot readers. I blog about JavaScript, like it’s my job, feel free to subscribe for a ton more posts like this.
Related Posts:
- Running Java in JavaScript
- JavaScript Talk at Northeastern University
- State of ECMAScript 4
- The World of ECMAScript
- JavaScript As A Language
Note: I’m not the creator of HotRuby, as mentioned elsewhere – it is the work of a highly-skilled Japanese developer.
HotRuby is a project which aims to port the Ruby Virtual Machine over to ECMAScript (allowing it to run, directly, in a browser using JavaScript or indirectly using ActionScript in Flash).
Currently the code works by using Ruby 1.9’s YARV (Yet Another Ruby VM) to compile down a Ruby script into opcodes, which are then serialized and passed to the browser for execution. It’s a little bit indirect but it still capable of creating a compelling result.
If you were to run one of the examples in your browser the actual chain of execution would be something like this:
- Script finds <script type=”text/ruby”></script> tags and extracts the inline Ruby code from them.
- The Ruby code is sent to the server via an XMLHttpRequest.
- The server-side CGI script (in Ruby, using Ruby 1.9) compiles the incoming Ruby into its associated opcodes and serializes it into a JSON data structure.
- The browser consumes the opcodes, translating it into JavaScript, and executes it.
To observe this full process we can take a look at the code in the provided benchmark and watch its full path through the server and final execution:
startTime = Time.new.to_f sum = "" 50000.times{|e| sum += e.to_s} endTime = Time.new.to_f puts (endTime - startTime).to_s + ' sec'
For example, observe this portion of the CGI script:
#!/usr/local/bin/ruby # Requires Ruby 1.9.0 # The license of this source is "Ruby License" require 'json' require 'cgi' cgi = CGI.new puts "Content-type: text/plain\n\n" puts VM::InstructionSequence.compile(cgi['src'], "src", 1, {}).to_a.to_json
and a sample of the opcode data returned by the server:
["YARVInstructionSequence\/SimpleDataFormat",1,1,1,{"arg_size":0,"local_size":4,"stack_max":3},"
and you can find the full client-side virtual machine here: HotRuby.js.
Perhaps most fascinating about this, though, is the speeds that are able to be achieved with this script. Granted, the above benchmark is rather contrived, but the end performance results are quite fascinating:
Firefox 3.0b5 | 2.47s |
Firefox 2 | 6.71s |
Ruby 1.8.2 | 12.25s |
We can see a 2.71x speed improvement from Firefox 2 to Firefox 3 and a 5x performance improvement over regular Ruby 1.8.2, running on the command-line.
It’s a fascinating time to be working with JavaScript. The performance improvements that are being provided to us by the browser afford us a realm of possibility that wasn’t, previously, viable. The fact that we’re even discussing running a virtual machine, implemented in JavaScript, is quite impressive. I’m curious to see what applications end up being built with this implementation – and within what context they end up using it.
micha17 (April 8, 2008 at 9:28 am)
isn’t that a bit unfair:
the classic ruby version is 1.8.2 but the CGI version is 1.9.
nevertheless.
Pedro Melo (April 8, 2008 at 9:45 am)
Hi,
micha17: why unfair? The CGI does not execute the Ruby benchmark, it only converts to JavaScript.
But back to the story: let me get this straight, because I’m having a hard time believing – You take Ruby code, convert it to JavaScript, and execute it in a browser, and after all that the runtime is between 1.8 and 5 time faster?
That’s impressive.
Kirk Cerny (April 8, 2008 at 10:01 am)
I wonder how this process compares with the speed of PHP or perl?
John Resig (April 8, 2008 at 10:31 am)
@micha17: Pedro is correct – the CGI only converts the Ruby code into the opcodes (compiles it) – it doesn’t actually execute it. The command-line version of Ruby gets all the same benefits (in that compile time is not taken into consideration).
@Pedro: That’s correct! Although, as I mentioned above, it is quite contrived. There was some discussion over at RubyInside where one commenter tried the Fibonacci sequence – seeing a much lower performance improvement. Although, he doesn’t mention what browser he was using, so it may not be as bad as he makes it out to be.
Már (April 8, 2008 at 10:38 am)
Uhm… why (outside of “proof of concept”) would anyone in his or her right mind want to do this?
markus (April 8, 2008 at 10:56 am)
‘Uhm… why (outside of “proof of concept”) would anyone in his or her right mind want to do this?’
Simple.
Because you can write in ruby code.
The key is that (one day) you abolish the limitation of javascript in certain situations. For the local network here for example (all using firefox mind you) I could concentrate on writing in ruby, and never have to touch javascript again.
This is a huge advantage. If you fail to see that I just cant help. But to the others I can assure that “web apps” that leave the “web” part out of the name will be a solid future. Not only Mozilla prism, but in general – the artificial separation of “web apps vs non-web apps” is bad.
It should be ONLY about apps, no matter where they originated from. (But i see this is slowly improving, so I am patient.)
Lets just hope that Ruby 1.9.x will be production ready within a forseeable time.
Scott Trudeau (April 8, 2008 at 11:01 am)
@Már that was my first reaction. I assume you could also generate the opcode for some scripts on the initial page request and include it in the page, rather than do the XHR loop.
Then you could write all Ruby code that runs both on the server and can be “compiled” for execution on the client as well. I always encounter this for complex form validation/input processing, where I often end up writing two sets of identical functions, one in the server-side language and one in JS. The reverse of this is probably something like Jaxer.
timothy (April 8, 2008 at 11:04 am)
Not a bad solution for running Ruby in the client. One group of people who might want this are the people doing IronRuby in Silverlight. They could fall back to this solution when Silverlight is not available.
Although JavaScript is probably my favorite language, I must admit I’m fascinated by the idea of running other languages in the browser.
Script# and Haxe seem especially well-thought out. In both cases, you write in another language (C# or Haxe), and then run the code through a compiler which translates to JavaScript. Both solutions produce nice code. But the advantage of type-checking at compile time may be outweighed by the oddness of seeing code you didn’t write at debug time.
timothy (April 8, 2008 at 11:14 am)
>>Uhm… why (outside of “proof of concept”) would anyone in his or her right mind want to do this?
It’s an easy way to obfuscation, for one reason. No obfuscation method is perfect, but this looks like a pretty good one. :-)
timothy (April 8, 2008 at 11:31 am)
I imagine it’s even faster when compiled to ActionScript than to JavaScript.
And since AIR runs on Webkit with fast JS and fast AS, people might reasonably do a full AIR app, mostly in Ruby.
Michael Jackson (April 8, 2008 at 11:42 am)
@Kirk: This is a pure guess but I imagine the virtual machine would be fairly similar for other languages. It’s all the same stuff right? Operators, functions, etc. The only major difference that I can see would be in PHP/perl’s speed via CGI in getting the opcodes back to the VM, and that may be significant. Like I said, pure guess.
@Már: Granted, there is very little use for the implementation in its current state. However, the possibility is fascinating. The point here is not to allow web developers to start writing all their old JavaScripts in Ruby and start serving them up with some help from XHR, but rather the potential of JavaScript (or the ECMA script interpreter) to serve as a platform for more robust applications, in this case, a virtual machine for the Ruby language. And it’s fast to boot. I believe it reveals just how far the language has progressed in recent years.
@John: Thanks for this post. You have a knack for sniffing out stories that I would never otherwise hear of. That saves me a lot of time searching them out myself. Thanks. ;)
Michael Jackson (April 8, 2008 at 11:48 am)
@markus: “Simple. Because you can write in ruby code.”
Syntactical differences are hardly a reason to slow down your script to a crawl (when compared to pure JavaScript).
“The key is that (one day) you abolish the limitation of javascript in certain situations.”
How do you abolish the “limitation” of JavaScript? Remember…the VM is written IN JavaScript. In the end, you’re executing JavaScript code…NOT Ruby!
Wanli (April 8, 2008 at 11:48 am)
What about the coming JS2? I think maybe after 1 or 2 years, we will take the JS2 as the first class language (or just CLR?), many other languages can be converted to JavaScript2 and run in the Tamarin VM.
timothy (April 8, 2008 at 11:48 am)
@Michael Jackson,
You may want to watch Ajaxian.com. I saw HotRuby there a week or two ago and my kids spent hours playing with the physics toys that are one of the demos. I check John’s blog and Ajaxian every morning.
timothy (April 8, 2008 at 11:50 am)
>>In the end, you’re executing JavaScript code…NOT Ruby!
What’s the difference? In the end, you’re really executing processor opcodes.
Wanli (April 8, 2008 at 11:54 am)
@Michael Jackson:
Maybe it’s not good solution now, but it tamarin gives JS performance a boost. I think it’s OK for ruby/python to finish some routine jobs (!glue up the mozilla2).
Michael Jackson (April 8, 2008 at 11:59 am)
@timothy: You’re absolutely right. I concede the point.
@Wanli: I agree that this could definitely have positive implications for the future. That’s what I said above (or was trying to say).
Wanli (April 8, 2008 at 12:01 pm)
@timothy:
If you write in ruby:
ruby -> ruby opcode -> XHR -> ruby “vm” in JS -> js code -> JIT compile (future)-> execute
While write in JS:
JS code -> XHR -> JIT compile (future)-> execute
If any mistakes, please let me known.
Bertrand Le Roy (April 8, 2008 at 12:05 pm)
That’s quite fascinating to see. The number of languages that can compile to JavaScript (or at least to a JS-executable form) seems to be growing every day. The performance qould probably need to be confirmed by a larger scale test but it would be interesting to see a post on why interpreting a language on another interpreter could be faster than running directly in a native interpreter. Doesn’t that say a lot about Ruby 1.8.2, more than it does about HotRuby?
Also, the one thing that would make HotRuby usable in reasonably-sized projects is debugger support: debugging opcode doesn’t seem to be a lot of fun…
What do you guys think about running Ruby code in Silverlight to achieve Ruby on the client?
Már (April 8, 2008 at 12:06 pm)
@Scott, that was my main point… why not simply serve the opcode on the first HTTP request and do away with the Bandwidth + DOM parsing + XHR overhead? The speed of the opcode translation+execution seems pretty trivial compared to that.
@markus: “Simple. Because you can write in ruby code.”
Somehow I knew someone would come up with that answer. :-)
timothy (April 8, 2008 at 12:23 pm)
@Wanli,
I don’t see the whole XHR step as relevant. In my opinion, this technique is most useful when you have already compile the Ruby. The output can be in the HTML, PHP, JS, or whatever file.
At the very least, it’s an interesting technique.
Have you seen this?
http://osteele.com/sources/javascript/functional/
It’s effectively JavaScript executing a handmade functional language.
We are stuck with JavaScript in the browser (for the good and the bad), but sometimes what you want is Forth, APL, Ruby, C#, or something else.
I come from the game industry. 20 years ago I would have bet you that there would have never, ever be an interpreter in a game. I was wrong. Once performance is sufficient, it ceases to drive all decisions.
timothy (April 8, 2008 at 12:36 pm)
>>What do you guys think about running Ruby code in Silverlight to achieve Ruby on the client?
Problems:
1) Development (as far as I can determine) requires you to buy Visual Studio. Doesn’t look like DLR languages are yet supported by Express versions of MS tools. And I’m not aware that any free (even as in beer) IDEs are ready to tackle this. I hate to be locked into one development solution.
2) Terrible installed-base problem. Flash is near-ubiquitous. I never even had Silverlight until I downloaded IE8 beta. This means many of your users will have to go through Silverlight installation or may even reject it. You’ll be chasing people away.
For now, if I were using Silverlight, I’d just check for it and not try to trigger the installation (maybe a badge telling people it’s Silverlight enhanced would be a reasonable option). I’d run my Silverlight code if Silverlight is there, or else fall back to Flash. That strategy makes most sense with JavaScript all around, so the code doesn’t have to be rewritten over and over.
But perhaps it would be reasonable with Ruby on Silverlight and HotRuby. You’d do all debugging possible on the Silverlight side and then just kinda print-n-pray otherwise.
Leo Horie (April 8, 2008 at 2:41 pm)
Perhaps also interesting is that the author of HotRuby has also written a Scheme interpreter written in Javascript. I think that (at least from a programming language enthusiast point of view) being able to use different programming paradigms in the browser allows programmers to write more concise and domain-specific code when lightning-speed isn’t that much of a concern.
Like timothy said, sometimes what you want is another language. Heck, many selector libraries essentially have ports of CSS to javascript. Maybe the next big thing will require continuations, or lisp macros. Who knows.
timothy (April 8, 2008 at 3:48 pm)
Also note that anything that gets used a lot (like the CSS selectors Leo mentions) has a chance of getting a native assist in the browser. Getting ANY tokenized interpreter in the browser would be great, because then you could target that interpret with any compiler. My ideal future browser has a JavaScript interpreter and
That’s pretty much what CLR and DLR are in Silverlight, and what the ActionScript token interpreter is.
Michael Neumann (April 8, 2008 at 5:26 pm)
HotRuby is a great project. But the benchmark is totally flawed. Please replace “+=” with “
Michael Neumann (April 8, 2008 at 5:27 pm)
with “<<” and you’ll see that Ruby is 10x faster than the HotRuby version.
http://www.ntecs.de/blog/articles/2008/03/26/rubyjs-vs-hotruby
Wanli (April 8, 2008 at 9:38 pm)
@timothy
Thank you for your link, it’s an interesting lib.
I agree with you that *sometimes what you want is Forth, APL, Ruby, C#, or something else.*, but it’s NOT for RIA, because I think even JS itself is not fast enought to do the HTML/SVG/Canvas animation jobs.
timothy (April 8, 2008 at 11:17 pm)
>>…I think even JS itself is not fast enought to do the HTML/SVG/Canvas animation jobs.
Yeah, but “fast enough” is always just a matter of time.
Asbjørn Ulsberg (April 9, 2008 at 2:49 am)
The fact that JavaScript is so much faster than Ruby, even with the little bit of network latency, op code translation, execution, etc., just makes it even clearer to me that what I really want is a server-side JavaScript framework.
I’m hoping the result of Steve Yegge’s endeavour in implementing “EcmaScript on Rails” will be available through the Google App Engine soon. The existing server-side JavaScript frameworks simply haven’t got a high enough degree of availability. Less penetration than Python and you’re out.
What I’d love to see, actually, is JavaScript in PHP. That is, the PHP execution environment, scripted with JavaScript (and with a proper object model supporting it), made available with a simple PHP module that could be plugged in to any existing PHP environment.
Michael Neumann (April 9, 2008 at 5:37 am)
@asbjorn: I don’t see the fact (that JavaScript is so much faster than Ruby) at all. I’d be nice to see a benchmark showing this.
Here is one:
http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=javascript&lang2=ruby
Javascript is quite good (it’s actually faster than Ruby in most benchmarks, but memory consumption is a lot higher!),
but this compares against Ruby 1.8.
Ruby 1.9 should be a lot faster. Try to compare against Python which should give an impression how fast Ruby 1.9 is roughly (~ 2x as fast as Spidermonkey Javascript).
But there might be faster implementations than Spidermonkey out there…
oldmoe (April 9, 2008 at 11:36 am)
There are huge semantic differences between += for strings in Ruby and JavaScript.
In Ruby you will get a huge amount of intermediate strings that will trigger the GC (several times I guess) for the Ruby implementation.
Not the case seemingly with the JavaScript Implementation.
As mentioned above, replacing += with << produces the same results but this time it is ~25x faster! (using Ruby 1.8.6 on my machine)
It would be crazy to think that an interpreter (even for compiled opcodes) written in JavaScript can outperform one written in C (Ruby’s interpretter)
I would expect that a decent implementation of any of both languages should perform similarly. I am actually looking forward for a Ruby implementation on Tamarin.
CptOatmeal (April 9, 2008 at 10:21 pm)
I completely agree. I posted on the RubyInside thread on this as well. The benchmarks are completely misleading and should in no way be taken to say that HotRuby is faster than any standard Ruby installation.
What’s more, saying that an implementation “is already faster than X” is misleading, as often languages are made slower by having to implement certain dynamic features. A subset of the language can be made to run very quickly. Creating a design that works with all the dynamic features and retains the same speed is the real feat.
Ali (April 10, 2008 at 8:45 am)
Do you guys know any similar project for Python?
Michael Neumann (April 10, 2008 at 9:32 am)
@Ali: No, except Pyjamas, which is a Python -> Javascript compiler (http://code.google.com/p/pyjamas/). But I think, as Python is bytecode compiled as well, it shouldn’t be too hard, if not easier because Python for example has immutable strings like Javascript.
Jonathan Fine (April 22, 2008 at 4:13 pm)
@Ali: The PyPy project has tools that compile a restricted subset of Python (RPython) to JavaScript.
http://codespeak.net/pypy/dist/pypy/doc/js/using.html
As someone else said, the great thing is that you can program in Python (or Ruby) rather than JavaScript.
That said, I’ve not used it, and the code it produces does not seem to be optimal. But the PyPy project is very thorough about achieving consistency – they want RPython on JavaScript to be the same as RPython in the ordinary Python interpreter, for example.
James Urquhart (April 28, 2008 at 3:05 pm)
Neat! Kind of reminds me of that SCUMM interpreter i writ in haXe a while back. I was able to execute SCUMM opcodes both in Flash 9 and JavaScript, enough to get a certain SCUMM game to load its first room, which in itself was neat.
Sadly though, never got round to any benchmarks. I more or less stopped work on it when i figured there wasn’t really a market for it. :)
( For reference, http://www.cuppadev.co.uk/2007/11/22/flash-plays-scumm-take-two/ )
John DeHope (April 28, 2008 at 3:18 pm)
My question is: how can I *replace* javascript with X, where X is some other language. I don’t hate JS, but it would be a lot of fun to be able to code web apps using an arbitrary language implementation of my own choice (creation?).
But anyway, this is really cool from a purely geek perspective.
Jose Dadural (May 20, 2008 at 11:18 am)
hi Leo Horie, whats up man? r u still in toronto?
email me back ([email protected]) if this is Leo who went to humber in 2000. thanks.
joshua (June 3, 2008 at 11:39 pm)
listen im new to ruby and i no the basics like how to tell it to do something when a certain word his typed in but i am just wondering if anyone knows of a website that gives u some codes to type
if anyone does can u pls email me and tell me at [email protected]