Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rubinius — niby MRI, ale zupełnie inaczej

Rubinius — niby MRI, ale zupełnie inaczej

Slides from a presentation delivered on 15.01.2013 at the Warsaw Ruby Users Group meetup.

http://wrug.eu/2013/01/09/spotkanie-styczniowe/

Jan Stępień

January 15, 2013
Tweet

More Decks by Jan Stępień

Other Decks in Programming

Transcript

  1. Nazywam się Jan Stępień, a ta prezentacja nosi tytuł
    Rubinius
    czyli niby MRI, ale zupełnie inaczej

    View Slide

  2. $ rbx
    irb(main):001:0> RUBY_VERSION
    => ”1.8.7”

    View Slide

  3. $ rbx -X19
    irb(main):001:0> RUBY_VERSION
    => ”1.9.3”

    View Slide

  4. Spis treści
    1. Filozofia
    2. Kompilacja JIT
    3. Odśmiecanie pamięci
    4. Wielowątkowość
    5. Co z tego wynika

    View Slide

  5. Filozofia

    View Slide

  6. MRI
    Język kluczowy to C

    View Slide

  7. Announcing RuDy: write Ruby native extensions in D
    programming language – Tomasz Stachewicz, EuRuKo 2009

    View Slide

  8. Profiling Ruby – Piotr Szotkowski, EuRuKo 2010

    View Slide

  9. Kod działa za
    wolno
    ⇒ Przepisz to w C,
    C++, D itp.

    View Slide

  10. Rubinius
    Język kluczowy to Ruby

    View Slide

  11. Array#insert w MRI i Rubinius
    static VALUE rb_ary_insert(int argc,
    VALUE *argv, VALUE ary)
    {
    long pos;
    if (argc < 1) {
    rb_raise(rb_eArgError,
    ”wrong number of arguments”);
    }
    rb_ary_modify_check(ary);
    if (argc == 1) return ary;
    pos = NUM2LONG(argv[0]);
    if (pos == -1) {
    pos = RARRAY_LEN(ary);
    }
    if (pos < 0) {
    pos++;
    }
    rb_ary_splice(ary, pos, 0,
    rb_ary_new4(argc - 1, argv + 1));
    return ary;
    }
    class Array
    def insert(idx, *items)
    Rubinius.check_frozen
    return self if items.length == 0
    idx = Rubinius::Type.coerce_to idx,
    Fixnum, :to_int
    idx += (@total + 1) if idx < 0
    if idx < 0
    raise IndexError,
    ”#{idx} out of bounds”
    end
    self[idx, 0] = items
    self
    end
    end
    (przeredegowano i usunięto to i owo w celu poprawy czytelności)

    View Slide

  12. Kod działa za
    wolno
    ⇒ Popraw maszynę
    wirtualną

    View Slide

  13. Kompilacja JIT

    View Slide

  14. Just-in-time compilation
    Kompilacja w ostatniej chwili

    View Slide

  15. Kompilacja wedle MRI
    require ’sinatra’
    get ’/ping’ do
    content_type ’text/pong’
    ’pong’
    end

    call
    self :get
    '/ping'
    :args →
    putself
    putstring ”sinatra”
    send :require, 1, nil, 8
    pop
    trace
    putself
    putstring ”/ping”
    send :get, 1, , 8

    View Slide

  16. Kompilacja wedle Rubinius
    . . . →
    putself
    putstring ”sinatra”
    send :require, 1, nil, 8
    pop
    trace
    putself
    putstring ”/ping”
    send :get, 1, , 8

    xor eax, eax
    test rax, rax
    je 0xf01dab1e
    pop rbp
    mov edi, 0x600d80
    jmp rax
    nop dword ptr [rax+0x0]
    mov eax, 0x600d80

    View Slide

  17. Kompilacja wedle Rubinius
    ...co można podsumować następująco:

    View Slide

  18. Kompilacja wedle Rubinius
    require ’sinatra’
    get ’/ping’ do
    content_type ’text/pong’
    ’pong’
    end

    xor eax, eax
    test rax, rax
    je 0xf01dab1e
    pop rbp
    mov edi, 0x600d80
    jmp rax
    nop dword ptr [rax+0x0]
    mov eax, 0x600d80
    LLVM

    View Slide

  19. Making Ruby Fast: e Rubinius JIT – Evan Phoenix
    https://blog.engineyard.com/2010/making-ruby-fast-the-rubinius-jit/

    View Slide

  20. Odśmiecanie pamięci

    View Slide

  21. Zarządzanie pamięcią w MRI
    Alokacja
    ▶ Pula pamięci podzielona na bloki
    ▶ Lista nieużywanych kawałków
    Zwalnianie
    1. Zatrzymaj działanie maszyny
    2. Zaznacz używane obiekty
    3. Usuń niezaznaczone

    View Slide

  22. MRI spędza 20% czasu na
    odśmiecaniu pamięci

    View Slide

  23. 20%

    View Slide

  24. 20%

    View Slide

  25. Garbage Collection and the Ruby Heap – Joe Damato,
    RailsConf 2010

    View Slide

  26. Spostrzeżenie
    Większość obiektów żyje bardzo krótko

    View Slide

  27. Żłobek → Młodzież → Starszyzna
    Kontener na większe obiekty

    View Slide

  28. 5 ings You’ll Love About Rubinius – Brian Ford
    https://blog.engineyard.com/2009/5-things-youll-love-about-rubinius/
    Garbage Collector – Dirkjan Bussink
    https://github.com/rubinius/rubinius/blob/master/web/doc/en/memory-
    system/garbage-collector.markdown

    View Slide

  29. Wielowątkowość

    View Slide

  30. Współbieżność
    vs.
    Równoległośc

    View Slide

  31. Współbieżność
    (ang. concurrency)
    wątek β
    wątek α
    czas

    View Slide

  32. Równoległość
    (ang. parallelism)
    wątek β
    wątek α
    czas

    View Slide

  33. threads = [1, 2].map do |x|
    Thread.new do
    100_000_000.times { x = -x }
    end
    end
    threads.map &:join

    View Slide

  34. $ time ruby wątki.rb
    30.73user 0.03system 0:31.45elapsed 97%CPU
    (0avgtext+0avgdata 5032maxresident)k
    2032inputs+0outputs (1major+1354minor)pagefaults 0swaps
    $ time rbx wątki.rb
    20.53user 0.04system 0:10.92elapsed 188%CPU
    (0avgtext+0avgdata 34280maxresident)k
    0inputs+0outputs (0major+9166minor)pagefaults 0swaps

    View Slide

  35. mri 31,5 s 5 MB 97%
    rbx 10,9 s 34 MB 188%

    View Slide

  36. Co z tego wynika

    View Slide

  37. Garść testów
    Życiowe
    ▶ rails — 1 000 zapytań do prostej aplikacji Rails 3.2
    ▶ sinatra — 10 000 zapytań do jeszcze prostszej
    aplikacji w Sinatrze
    Nieżyciowe
    ▶ macierze — mnożenie macierzy (źródło:
    The Computer Language Benchmarks Game)
    ▶ wątki — to samo co kilka slajdów temu

    View Slide

  38. 0 10 20 30 40 50
    rails sinatra wątki
    macierze
    rbx
    mri
    Czas wykonania [s]
    Rubinius: commit fd80bd skompilowany GCC 4.7.2. MRI: pakiet Arch Linux x86-64 w wersji 1.9.3_p362-1.

    View Slide

  39. Rubinius - Use Ruby – Karol Hosiawa, KRUG 11.2011
    http://hosiawak.github.com/rubinius_presentation/

    View Slide

  40. [email protected]
    http://stepien.cc/~jan
    @janstepien
    Serdecznie
    dziękuję

    View Slide

  41. Uzupełnienia po prezentacji
    Niniejszy slajd ma na celu uzupełnienie prezentacji przedstawionej na
    spotkaniu Warsaw Ruby Users Group w dniu 15.01.2013.
    W przeprowadzonym przeze mnie eksperymencie, w którym MRI zużywał
    na odśmiecanie pamięci 20% czasu procesora, w wypadku Rubinius czas
    spędzony w GC stanowił 5% łącznego czasu wykonania.
    Przed każdym spośród wykonanych testów dokonano uruchomienia,
    którego wyniki były odrzucane, aby pozwolić systemowi operacyjnemu
    na umieszczenie niezbędnych plików w pamięci podręcznej. Testy Ruby
    on Rails i Sinatra były prowadzone przy pomocy serwera in 1.5.0. Ze
    względu na fakt, że in korzysta z rozszerzeń napisanych w C, warto
    dokonać powtórnych testów na innych serwerach, np. (sic!) WEBrick. Czas
    odpowiedzi na zapytania HTTP mierzono przy pomocy ApacheBench 2.3.
    W wypadku obu maszyn wirtualnych testy poprzedzone były zadaniem
    tysiąca niemierzonych zapytań HTTP. Miało to na celu umożliwienie
    Rubinius rozpoczęcia kompilacji JIT przed właściwymi testami.
    Kod testów można uzyskać pod adresem
    https://bitbucket.org/jstepien/wrug-2013-01-15

    View Slide

  42. Prezentację przygotowano przy pomocy pakietu L
    A
    TEX.
    © 2013 Jan Stępień. Część praw zastrzeżono.

    View Slide