Rubinius: Ruby написанный на Ruby

37
Rubinius: Ruby, написанный на Ruby Самсонов Иван

description

Rubinius: Ruby written on Ruby.Devcon '10. Moscow, Russia, 17, May

Transcript of Rubinius: Ruby написанный на Ruby

Page 1: Rubinius: Ruby написанный на Ruby

Rubinius: Ruby, написанный на Ruby

Самсонов Иван

Page 2: Rubinius: Ruby написанный на Ruby

Летом 2006 года, где-то в США

А не написать ли мне свой Ruby с

блекджеком и шлюхами?

Page 3: Rubinius: Ruby написанный на Ruby

Что такое Rubinius?

RubyLLVM

JIT

Engine Yard

Evan Phoenix VM

Melbourne

Bytecode

Page 4: Rubinius: Ruby написанный на Ruby

Программа, которая транслирует код программы на Ruby, например:

puts 123

в эффективный машинный код с последующим его исполнением:

push %rbp;

mov %rsp, %rbp;

push %rbx; subq $0x98, %rsp;

cmp $0x0, 0x10(%rcx);

call 0xffffffffff472010;

jmp 0x9c;

Rubinius это:

Page 5: Rubinius: Ruby написанный на Ruby

Имплементация языка программирования Ruby

Rubinius это:

Page 6: Rubinius: Ruby написанный на Ruby

Нормально ли, что Rubinius написан на Ruby?

Да! Ведь, например:• изрядная часть языка Java написана на

нём самом;• Где не получается использовать Ruby,

используется C++;

Page 7: Rubinius: Ruby написанный на Ruby

Нормально ли, что 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;}

Page 8: Rubinius: Ruby написанный на Ruby

Нормально ли, что 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

Page 9: Rubinius: Ruby написанный на Ruby

Почему Rubinius?

Page 10: Rubinius: Ruby написанный на Ruby

Почему Ruby?

Page 11: Rubinius: Ruby написанный на Ruby

Потому, что Ruby:

•Динамичный;•Человечный;•Удобный.

Page 12: Rubinius: Ruby написанный на Ruby

...но при этом Ruby медленный

Page 13: Rubinius: Ruby написанный на Ruby

Одна из целей проекта Rubinius - сделать Ruby

быстрым

Page 14: Rubinius: Ruby написанный на Ruby

История Rubinius

Старт проекта

Engine Yard нанимает Эвана

Команда расширяется

Запуск Rails

VM на C++

stackfull бренчмержится в master

JITПовторный запуск Rails

Page 15: Rubinius: Ruby написанный на Ruby

Преимущества Rubinius

• Компактное быстрое ядро VM;• сборщик мусора, основанный на

поколениях;• поддержка расширений языка C;• большая часть кода реализована на Ruby;• JIT;• RubySpec;

Page 16: Rubinius: Ruby написанный на Ruby

Сборщик мусора

•Перемещающая стратегия;

• Immix mark-region сборщик;

Page 17: Rubinius: Ruby написанный на Ruby

Стадии компилятора байткода

.rb файл

Node дерево

sexps

AST

bytecode

Page 18: Rubinius: Ruby написанный на Ruby

Результат компилятора байткода

def foo(a,b) a + bend

0000:  push_local                 0    # a0002:  push_local                 1    # b0004:  meta_send_op_plus          :+0006:  ret

Page 19: Rubinius: Ruby написанный на Ruby

Стадии JIT

bytecode

LLVM IR машинный код

Page 20: Rubinius: Ruby написанный на Ruby

Входящий Ruby-код для JIT

class Flower def bloom(*a) a endend

Page 21: Rubinius: Ruby написанный на Ruby

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

Page 22: Rubinius: Ruby написанный на Ruby

Дальнейшая оптимизация:

Method Inlining

Page 23: Rubinius: Ruby написанный на Ruby

Примитивы

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

Page 24: Rubinius: Ruby написанный на Ruby

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

Page 25: Rubinius: Ruby написанный на Ruby

Плагины компилятора

# -*- array_zen -*-

q = +[ x**2 , x.in([1,2,3])]

p q # => [1, 4, 9]

Page 26: Rubinius: Ruby написанный на Ruby

Тестирование языка программирования

• 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

Page 27: Rubinius: Ruby написанный на Ruby

Проблемы с Rubinius:

• Отсутствие поддержки Windows;• Небольшое сообщество;• Непригоден для продакшена;• Несовместимость с некоторыми гемами

(C, Ruby);• Отсутствие актуальной документации;

Page 28: Rubinius: Ruby написанный на Ruby

Пример «багов»:

x = 0

loop do

puts x > -123 # => true

end

Page 29: Rubinius: Ruby написанный на Ruby

Планы по развитию:

• JIT• Debugger• 1.9• Windows

Page 30: Rubinius: Ruby написанный на Ruby

Бенчмарки

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)

Page 31: Rubinius: Ruby написанный на Ruby

Рекурсия

def fib(n) if (n < 2) n else fib(n-1) + fib(n-2) endend

Page 32: Rubinius: Ruby написанный на Ruby

Рекурсия

Page 33: Rubinius: Ruby написанный на Ruby

Хеш функция

def foo

hash = {}

100.times {|i| hash[i] = 0}

end

Page 34: Rubinius: Ruby написанный на Ruby

Хеш функция

Page 35: Rubinius: Ruby написанный на Ruby

Простое Rails приложение

• Rails 2.3.5

• WEBrick

• ab -c 5 -n 1000 http://127.0.0.1:3000/

• authlogick example

Page 36: Rubinius: Ruby написанный на Ruby

Простое Rails приложение

Page 37: Rubinius: Ruby написанный на Ruby

А ты стал контрибутором Rubinius?