First Look at Mruby

mruby is minimalistic Ruby, developed by Matz (Ruby’s creator) and funded by the Japanese ministry of Economy.

I’ve been waiting for this to go public since Matz’ early announcements of him being working on it. This is very exciting.

Installing

  $ git clone https://github.com/mruby/mruby
  $ make

Compilation is a fantastic error-less breeze, around 20 seconds.

Hello mruby

Lets see how this thing should work.

$ cd bin
$ cat > hello.rb
puts "hello mruby!"
^D
$ ./mruby hello.rb
hello mruby!

Done. Quick sanity check for mruby, very cool. Lets try something more complicated.

require 'benchmark'
require 'digest/md5'
puts Benchmark.measure {
  puts "goo"
}
puts  Digest::MD5.hexdigest "hello mruby!"
puts "hello mruby!"

No rubygems so no errors while requiring any of these, and we can confirm (unsurprisingly) that we can’t treat it like a normal ruby. So we get:

$ ./mruby hello.rb
#<NameError: uninitialized constant Benchmark>

Yup, no benchmark, so lets use time. I’ve ported a benchmark sample from the computer language shootout, removing mruby incompatible things and bridging the gap between mruby and ruby so we can just toggle each and run.

You can take a look at it here: https://gist.github.com/2438540.

Its Not Faster

I had 0-knowledge about what mruby should do here. Since I’m familiar with Lua’s speed and mruby aiming for that space, I was hoping for a surprise.

A quick run shows that the mruby interpreter is considerably slower, and giving off different results, I don’t care about that for now:

  $ time ruby n-body.rb
  -0.16854649420142517
  -0.1685643614266391
  ruby n-body.rb  1.68s user 0.05s system 84% cpu 2.044 total

  $ time ./mruby n-body.rb
  -5.99182358773761e+154
  NaN
  ./mruby n-body.rb  5.32s user 0.04s system 90% cpu 5.900 total


  $ time ./mruby -b n-body.mrb
  -5.99182358773761e+154
  NaN
  ./mruby -b n-body.mrb  5.12s user 0.04s system 90% cpu 5.713 total

In mruby you can compile your code to bytecode. I’ve compiled it using mrbc which also lives in bin into n-body.mrb and ran it above using the -b flag: mruby -b.

Just a funny fact, if you dump the compiled content, for the magic number, you get:

RITE0009000000090000MATZ

The Real Fun Is Here

Lets look at what the executable mruby is, this is quite cool:

if (args.mrbfile) {
  n = mrb_load_irep(mrb, args.rfp);
}
else {
  p = mrb_parse_file(mrb, args.rfp);
  if (!p || !p->tree || p->nerr) {
    cleanup(&args);
    return -1;
  }

  if (args.verbose)
    parser_dump(mrb, p->tree, 0);

  n = mrb_generate_code(mrb, p->tree);
  mrb_pool_close(p->pool);
}

if (n >= 0) {
  if (args.verbose)
    codedump_all(mrb, n);

  if (!args.check_syntax) {
    mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_nil_value());
    if (mrb->exc) {
mrb_funcall(mrb, mrb_nil_value(), "p", 1, mrb_obj_value(mrb->exc));
    }
  }
}

This shows why mruby is so awesome; you can embed it – and the perfect example for it is the mruby executable itself.