Download - Rubinius: Ruby написанный на Ruby
Rubinius: Ruby, написанный на Ruby
Самсонов Иван
Летом 2006 года, где-то в США
А не написать ли мне свой Ruby с
блекджеком и шлюхами?
Что такое Rubinius?
RubyLLVM
JIT
Engine Yard
Evan Phoenix VM
Melbourne
Bytecode
Программа, которая транслирует код программы на Ruby, например:
puts 123
в эффективный машинный код с последующим его исполнением:
push %rbp;
mov %rsp, %rbp;
push %rbx; subq $0x98, %rsp;
cmp $0x0, 0x10(%rcx);
call 0xffffffffff472010;
jmp 0x9c;
Rubinius это:
Имплементация языка программирования Ruby
Rubinius это:
Нормально ли, что Rubinius написан на Ruby?
Да! Ведь, например:• изрядная часть языка Java написана на
нём самом;• Где не получается использовать Ruby,
используется C++;
Нормально ли, что Rubinius написан на Ruby?
static VALUE rb_ary_collect(ary) VALUE ary;{ long i; VALUE collect;
if (!rb_block_given_p()) { return rb_ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr);
}
collect = rb_ary_new2(RARRAY(ary)->len); for (i = 0; i < RARRAY(ary)->len; i++) {
rb_ary_push(collect, rb_yield(RARRAY(ary)->ptr[i])); } return collect;}
Нормально ли, что Rubinius написан на Ruby?
module Enumerable def collect if block_given? ary = [] each { |o| ary << yield(o) } ary else to_a end end
alias_method :map, :collectend
Почему Rubinius?
Почему Ruby?
Потому, что Ruby:
•Динамичный;•Человечный;•Удобный.
...но при этом Ruby медленный
Одна из целей проекта Rubinius - сделать Ruby
быстрым
История Rubinius
Старт проекта
Engine Yard нанимает Эвана
Команда расширяется
Запуск Rails
VM на C++
stackfull бренчмержится в master
JITПовторный запуск Rails
Преимущества Rubinius
• Компактное быстрое ядро VM;• сборщик мусора, основанный на
поколениях;• поддержка расширений языка C;• большая часть кода реализована на Ruby;• JIT;• RubySpec;
Сборщик мусора
•Перемещающая стратегия;
• Immix mark-region сборщик;
Стадии компилятора байткода
.rb файл
Node дерево
sexps
AST
bytecode
Результат компилятора байткода
def foo(a,b) a + bend
0000: push_local 0 # a0002: push_local 1 # b0004: meta_send_op_plus :+0006: ret
Стадии JIT
bytecode
LLVM IR машинный код
Входящий Ruby-код для JIT
class Flower def bloom(*a) a endend
JIT – результат преобразования
0x2280010 sub $0xc, %esp
0x2280013 mov 0x1c(%esp), %eax
0x2280017 mov %eax, 0x4(%esp)
0x228001b mov 0x10(%esp), %eax
0x228001f mov %eax, (%esp)
0x2280022 mov $0x0, 0x8(%esp)
0x228002a call 0xfffffffffde9d640 ;
0x11d650 rbx_construct_splat
0x228002f add $0xc, %esp
0x2280032 ret
Дальнейшая оптимизация:
Method Inlining
Примитивы
class Fixnum : public Integer {
public:
// Ruby.primitive! :fixnum_or
Integer* bit_or(STATE, Fixnum* other);
};
class Fixnum < Integer
def |(o)
Ruby.primitive :fixnum_or
end
end
Backtraceputs "123" + 1
bin/rbx z.rb
Coercion error: 1.to_str => String failed (TypeError)
Backtrace: Type.coerce_to at kernel/common/type.rb:22 Kernel(String)#StringValue at kernel/common/kernel.rb:112 String#+ at kernel/common/string.rb:78 main.__script__ at z.rb:1 Rubinius::CodeLoader#load_script at kernel/delta/codeloader.rb:65 Rubinius::CodeLoader.load_script at kernel/delta/codeloader.rb:88 Rubinius::Loader#script at kernel/loader.rb:435 Rubinius::Loader#main at kernel/loader.rb:526 Rubinius::Loader.main at kernel/loader.rb:552 Object#__script__ at kernel/loader.rb:564
ruby z.rb
z.rb:1:in `+': can't convert Fixnum into String (TypeError)from z.rb:1
Плагины компилятора
# -*- array_zen -*-
q = +[ x**2 , x.in([1,2,3])]
p q # => [1, 4, 9]
Тестирование языка программирования
• Mspec• RubySpec
describe "Array#shift" do it "removes and returns the first element" do a = [5, 1, 1, 5, 4] a.shift.should == 5 end
it "returns nil when the array is empty" do [].shift.should == nil endend
Проблемы с Rubinius:
• Отсутствие поддержки Windows;• Небольшое сообщество;• Непригоден для продакшена;• Несовместимость с некоторыми гемами
(C, Ruby);• Отсутствие актуальной документации;
Пример «багов»:
x = 0
loop do
puts x > -123 # => true
end
Планы по развитию:
• JIT• Debugger• 1.9• Windows
Бенчмарки
rubinius 1.0.0 (1.8.7 e6c32afd 2010-05-14 JI)
ruby 1.9.2dev (2010-04-14 trunk 27342)
ruby 1.8.7 (2010-01-10 patchlevel 249)
jruby 1.6.0.dev (ruby 1.8.7 patchlevel 249) (2010-04-14
7cb1298)
MacRuby version 0.6 (ruby 1.9.0)
Рекурсия
def fib(n) if (n < 2) n else fib(n-1) + fib(n-2) endend
Рекурсия
Хеш функция
def foo
hash = {}
100.times {|i| hash[i] = 0}
end
Хеш функция
Простое Rails приложение
• Rails 2.3.5
• WEBrick
• ab -c 5 -n 1000 http://127.0.0.1:3000/
• authlogick example
Простое Rails приложение
А ты стал контрибутором Rubinius?