33fd42e58d34f65d5285e6e488ec30aa.ppt
- Количество слайдов: 37
Rubinius: Ruby, написанный на Ruby Самсонов Иван, Оверсан-Скалакси
Летом 2006 года, где-то в США А не написать ли мне свой Ruby с блекджеком и шлюхами?
Что такое Rubinius? Evan Phoenix Bytecode JIT VM Ruby Melbourne Engine Yard LLVM
Rubinius это: Программа, которая транслирует код программы на Ruby, например: puts 123 в эффективный машинный код с последующим его исполнением: push %rbp; mov %rsp, %rbp; push %rbx; subq $0 x 98, %rsp; cmp $0 x 0, 0 x 10(%rcx); call 0 xfffff 472010; jmp 0 x 9 c;
Rubinius это: Имплементация языка программирования Ruby
Нормально ли, что 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_new 4(RARRAY(ary)->len, RARRAY(ary)->ptr); } collect = rb_ary_new 2(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 alias_method : map, : collect end
Почему Rubinius?
Почему Ruby?
Потому, что Ruby: • Динамичный; • Человечный; • Удобный.
. . . но при этом Ruby медленный
Одна из целей проекта Rubinius - сделать Ruby быстрым
История Rubinius Старт проекта Команда расширяется Engine Yard нанимает Эвана Запуск Rails VM на C++ JIT stackfull бренч мержится в master Повторный запуск Rails
Преимущества Rubinius • • • Компактное быстрое ядро VM; сборщик мусора, основанный на поколениях; поддержка расширений языка C; большая часть кода реализована на Ruby; JIT; Ruby. Spec;
Сборщик мусора • Перемещающая стратегия; • Immix mark-region сборщик;
Стадии компилятора байткода. rb файл Node дерево sexps bytecode AST
Результат компилятора байткода def foo(a, b) a + b end 0000: push_local 0 # a 0002: push_local 1 # b 0004: meta_send_op_plus : + 0006: ret
Стадии JIT bytecode LLVM IR машинный код
Входящий Ruby-код для JIT class Flower def bloom(*a) a end
JIT – результат преобразования 0 x 2280010 sub $0 xc, %esp 0 x 2280013 mov 0 x 1 c(%esp), %eax 0 x 2280017 mov %eax, 0 x 4(%esp) 0 x 228001 b mov 0 x 10(%esp), %eax 0 x 228001 f mov %eax, (%esp) 0 x 2280022 mov $0 x 0, 0 x 8(%esp) 0 x 228002 a call 0 xfffffde 9 d 640 ; 0 x 11 d 650 rbx_construct_splat 0 x 228002 f add $0 xc, %esp 0 x 2280032 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
Backtrace puts "123" + 1 ruby z. rb: 1: in `+': can't convert Fixnum into String (Type. Error) from z. rb: 1 bin/rbx z. rb Coercion error: 1. to_str => String failed (Type. Error) Backtrace: Type. coerce_to Kernel(String)#String. Value String#+ main. __script__ Rubinius: : Code. Loader#load_script Rubinius: : Code. Loader. load_script Rubinius: : Loader#main Rubinius: : Loader. main Object#__script__ at at at kernel/common/type. rb: 22 kernel/common/kernel. rb: 112 kernel/common/string. rb: 78 z. rb: 1 kernel/delta/codeloader. rb: 65 kernel/delta/codeloader. rb: 88 kernel/loader. rb: 435 kernel/loader. rb: 526 kernel/loader. rb: 552 kernel/loader. rb: 564
Плагины компилятора # -*- array_zen -*q = +[ x**2 , x. in([1, 2, 3])] p q # => [1, 4, 9]
Тестирование языка программирования • Mspec • Ruby. Spec 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 end
Проблемы с 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 e 6 c 32 afd 2010 -05 -14 JI) ruby 1. 9. 2 dev (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 7 cb 1298) Mac. Ruby version 0. 6 (ruby 1. 9. 0)
Рекурсия def fib(n) if (n < 2) n else fib(n-1) + fib(n-2) end
Рекурсия
Хеш функция 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?
33fd42e58d34f65d5285e6e488ec30aa.ppt