Rubinius

Use Ruby

http://rubini.us

About me

Karol Hosiawa - hosiawak

Agenda

What is Rubinius ?

Compatibility

Why Rubinius ?

Why Rubinius ?

What are the foundations ?

Code - Rubinius - Highlights

Code - MRI - Highlights

Code - Comparison

Integer

Integer#times

MRI

static VALUE
int_dotimes(VALUE num)
{
    RETURN_ENUMERATOR(num, 0, 0);

    if (FIXNUM_P(num)) {
        long i, end;

        end = FIX2LONG(num);
        for (i=0; i<end; i++) {
            rb_yield(LONG2FIX(i));
        }
    }
    else {
        VALUE i = INT2FIX(0);

        for (;;) {
            if (!RTEST(rb_funcall(i, '<', 1, num)))
                break;
            rb_yield(i);
            i = rb_funcall(i, '+', 1, INT2FIX(1));
        }
    }
    return num;
}

Rubinius

def times
  return to_enum(:times) unless block_given?

  i = 0
  while i < self
    yield i
    i += 1
  end
  self
end

Integer#times

Integer#times

Code - Rubinius

Mixology

Code - It's not just core/stdlib classes

Rubinius - very powerful features

Rubinius - very powerful features

Custom bytecode generation, eg.

def hello
  Rubinius.asm do
    push_literal "hello "
    push_literal "world"
    send :+, 1
  end
end
irb> hello
=> "hello world"

Code in Rubinius

What are the foundations ?

Ruby

Garbage Collector (GC) - MRI 1.8

GC - MRI 1.8 - Patches

GC - MRI 1.9

GC - MRI 1.9 - Patches

GC - Rubinius

GC - Rubinius

Rubinius GC - Nursery

Rubinius GC - Young generation

Rubinius GC - Mature generation

Rubinius GC - Large objects

What does it all mean in practice ? - MRI 1.8

What does it all mean in practice ? - MRI 1.9

What does it all mean in practice ? - Rubinius GC

Why is it important ?

How much better is Rubinius GC ?

GC bench - https://gist.github.com/1008305

What are the foundations ?

Interpreter - MRI

Interpreter - MRI

Interpreter - Rubinius

Rubinius - Interpreter/compiler overview

Rubinius - Compiler

AST

"1 + 2".to_ast

SendWithArguments
  @line: 1
  @name: :+
  @privately: false
  @check_for_local: false
  @vcall_style: false
  @block: nil
  @arguments: \
    ActualArguments
      @line: 1
      @splat: nil
      @array: [
        FixnumLiteral [0]
          line: 1
          value: 2
      ]
  @receiver: \
    FixnumLiteral
      @line: 1
      @value: 1

Bytecode

============= :__script__ ==============
Arguments:   0 required, 0 post, 0 total
Arity:       0
Locals:      0
Stack size:  2
Lines to IP: 1: 0..6

0000:  meta_push_1
0001:  meta_push_2
0002:  meta_send_op_plus          :+
0004:  pop
0005:  push_true
0006:  ret
----------------------------------------

Bytecode compiler

Interpreter

JIT Compiler - Inlining

./bin/rbx -Xjit.show=true

def simple
  1
end

1_000_000.times { simple }
[[[ JIT finished background compiling  (block) ]]]
[[[ JIT finished background compiling  (method) ]]]

Inlining method 'simple':

1_000_000.times { 1 }

Inlining block into Integer#times:

i = 0
while i < self
  1 # THIS WAS yield i
  i += 1
end

Performance - Approach

JVM

Rubinius - How does it perform ?

Array#map

String#split

Hash#merge

Real World - Red Black Tree

Real World - AVI Protobuf

Rubinius - Performance summary

I want to contribute

I want to contribute

QUIZ - Question 1

push_int 3
push_int 4
send     :+, 1

What value is on the stack after executing the above bytecode ?

QUIZ - Question 2

Should you be afraid of creating a large number of temporary objects in Rubinius ?

Questions ?

Thank you!

http://hosiawak.github.com/rubinius_presentation

/

#