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

What If...?: Ruby 3

What If...?: Ruby 3

Slides for my RubyConf talk on the possible futures of Ruby.

Eric Weinstein

November 15, 2017
Tweet

More Decks by Eric Weinstein

Other Decks in Technology

Transcript

  1. What If...?: Ruby 3
    # Eric Weinstein
    # RubyConf 2017
    # New Orleans, LA, USA
    # 15 November 2017

    View Slide

  2. The Future of Ruby
    Part III: The Future(s)

    View Slide

  3. View Slide

  4. Part 0: Hello!

    View Slide

  5. About Me
    eric_weinstein = {
    employer: 'Fox Networks Group',
    github: 'ericqweinstein',
    twitter: 'ericqweinstein',
    website: 'ericweinste.in'
    }
    30% off with RUBYCONF30! ->

    View Slide

  6. Agenda
    • What If...? comics
    • The power of stories
    • Slide vs. speech
    • Three stories

    View Slide

  7. What If...?

    View Slide

  8. View Slide

  9. Ruby 3x3
    • Goal: Ruby 3 will be 3x faster than Ruby 2
    • I think we’ll get there! But what else will we get?
    • Three "What if...?" scenarios: types, environment,
    concurrency

    View Slide

  10. (It wasn’t.)

    View Slide

  11. View Slide

  12. Part 1: What if Ruby Had a
    Static Type System?

    View Slide

  13. Static vs. Dynamic
    • Static: variable types (e.g. Fixnum, String,
    Symbol) are known at compile time
    • May or may not make use of type inference
    • Dynamic: variable types are not known until runtime

    View Slide

  14. Weak vs. Strong
    • Don’t @ me
    • Weak: implicit type conversion
    • Strong: no implicit type conversion
    • Ruby is strongly, dynamically typed

    View Slide

  15. (It encourages him.)

    View Slide

  16. Weak vs. Strong
    • Don’t @ me
    • Weak: implicit type conversion
    • Strong: no implicit type conversion
    • Ruby is strongly, dynamically typed

    View Slide

  17. YARV
    Tokenize -> lex -> parse -> compile to bytecode ->
    execute!

    View Slide

  18. 10.times do |n|
    puts n
    end
    [[[1, 0], :on_int, "10"],
    [[1, 2], :on_period, "."],
    [[1, 3], :on_ident, "times"],
    [[1, 8], :on_sp, " "],
    [[1, 9], :on_kw, "do"],
    [[1, 11], :on_sp, " "],
    [[1, 12], :on_op, "|"],
    [[1, 13], :on_ident, "n"],
    [[1, 14], :on_op, "|"],
    [[1, 15], :on_ignored_nl, "\n"],
    [[2, 0], :on_sp, " "],
    [[2, 2], :on_ident, "puts"],
    [[2, 6], :on_sp, " "],
    [[2, 7], :on_ident, "n"],
    [[2, 8], :on_nl, "\n"],
    [[3, 0], :on_kw, "end"],
    [[3, 3], :on_nl, "\n"]]
    Credit: Ruby Under a Microscope, Pat Shaughnessy

    View Slide

  19. Parsing
    • LALR Algorithm
    • $ ruby -y example.rb
    Credit: Ruby Under a Microscope, Pat Shaughnessy

    View Slide

  20. YARV Bytecode
    RubyVM::InstructionSequence.compile(code).disasm

    View Slide

  21. == disasm: #@>================================
    == catch table
    | catch type: break st: 0002 ed: 0008 sp: 0000 cont: 0008
    |------------------------------------------------------------------------
    0000 trace 1 ( 1)
    0002 putobject 10
    0004 send , , block in
    0008 leave
    == disasm: #@>=======================
    == catch table
    | catch type: redo st: 0002 ed: 0010 sp: 0000 cont: 0002
    | catch type: next st: 0002 ed: 0010 sp: 0000 cont: 0010
    |------------------------------------------------------------------------
    local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: [email protected], kwrest: -1])
    [ 2] n
    0000 trace 256 ( 1)
    0002 trace 1 ( 2)
    0004 putself
    0005 getlocal_OP__WC__0 2
    0007 opt_send_without_block ,
    0010 trace 512 ( 3)
    0012 leave ( 2)

    View Slide

  22. View Slide

  23. ($ brew uninstall ruby && brew
    install crystal)

    View Slide

  24. class Account
    def initialize
    @balance = 0
    end
    def balance
    @balance
    end
    def deposit(amount)
    @balance += amount
    end
    def withdraw(amount)
    @balance -= amount
    end
    end

    View Slide

  25. Dependent Types
    *example> getTransactions
    [4, 8, 15, 16, 23, 42] : List Nat

    View Slide

  26. [-4, 8, 15, 16, 23, 42]
    example.idr:2:17:When checking right hand side of
    getTransactions with expected type
    List Nat
    When checking argument x to constructor
    Prelude.List.:::
    Can't find implementation for Neg Nat

    View Slide

  27. class Account
    def initialize
    @balance = 0
    end
    type :balance, Nat
    def balance
    @balance
    end
    type :deposit, Nat, Nat
    def deposit(amount)
    @balance += amount
    end
    type :withdraw, Nat
    def withdraw(amount)
    @balance -= amount
    end
    end

    View Slide

  28. class Account
    def initialize
    @balance = 0
    end
    type :balance, Nat
    def balance
    @balance
    end
    type :deposit, Nat, Nat
    def deposit(amount)
    @balance += amount
    end
    type :withdraw, Nat
    def withdraw(amount)
    @balance -= amount
    end
    end

    View Slide

  29. def withdraw(amount: Nat)
    @balance -= amount
    end

    View Slide

  30. def withdraw(Nat amount)
    @balance -= amount
    end

    View Slide

  31. def withdraw(Float amount)
    @balance -= amount
    end

    View Slide

  32. View Slide

  33. (Fun fact: he knows way more
    about ‘90s cartoons than code.)

    View Slide

  34. Good Change/Bad Change?
    • Dynamic typing: Trade execution speed for
    programmer speed, flexibility, and metaprogramming
    magicks
    • Static typing: Trade programmer speed for execution
    speed and compile-time checks
    • Dependent typing: Trade flexibility for ultra
    powerful compile-time checks

    View Slide

  35. Part 2: What if Ruby Ran in
    the Browser?

    View Slide

  36. ( )

    View Slide

  37. ( )

    View Slide

  38. View Slide

  39. ['1', '2', '3'].map(parseInt);
    // => [ 1, NaN, NaN ]
    ['1', '2', '3'].map((n) => parseInt(n, 10));
    // => [ 1, 2, 3 ]

    View Slide

  40. It Does! (Sort Of)

    View Slide

  41. https://www.destroyallsoftware.com/talks/the-birth-
    and-death-of-javascript

    View Slide

  42. View Slide

  43. Good Change/Bad Change?
    • Server-side only: Keep control over the environment
    but still have to write JavaScript
    • With the browser (compile-to-JS): Get the wild west
    of the browser and still have to read JavaScript
    • WASM: Get the wild west of the browser, but get to
    write Ruby in all the places

    View Slide

  44. Part 3: What if Ruby Had No
    GIL?

    View Slide

  45. I Know, I Know
    • It’s not a GIL anymore
    • GVL is the new GIL
    • What did I say about @ing me

    View Slide

  46. (Number of post-talk questions
    is now: 0)

    View Slide

  47. What is the GVL?
    • The Global VM Lock (formerly Global Interpreter
    Lock) is a mutual-exclusion lock held by a thread
    • The GVL prevents any other thread from running
    while the thread holding it is executing
    • Not all Rubies have a GVL (CRuby does, JRuby does
    not)

    View Slide

  48. (Want to hear a Ruby joke?)

    View Slide

  49. (Concurrency!)

    View Slide

  50. Concurrency vs. Parallelism
    • Concurrency: do one thing at a time, but constantly
    switch among them to make progress on all of them
    • Parallelism: do multiple things at once

    View Slide

  51. Thread Safety
    • The GVL’s job is to avoid race conditions and
    prevent data corruption
    • It prevents threads from sharing code unsafely,
    e.g. Array#<<

    View Slide

  52. Ye Olde Guildes
    Credit: http://olivierlacan.com/posts/concurrency-in-ruby-3-with-guilds/

    View Slide

  53. Actors?

    View Slide

  54. Stealing from Go
    def fetch
    # Lycos, go get it!
    end
    list_of_urls.each do |url|
    go fetch url
    end

    View Slide

  55. Stealing from Clojure
    list_of_urls.pmap(&:fetch)

    View Slide

  56. (repeatedly #(interleave
    '(:coffee :panic)))

    View Slide

  57. (repeatedly #(interleave '(☕ )))

    View Slide

  58. (Don’t encourage him.)

    View Slide

  59. Good Change/Bad Change?
    • With the GVL: thread safety (at the cost of
    performance)
    • Without the GVL: true parallelism and significant
    performance gains for CPU-intensive work (at the
    cost of safety)

    View Slide

  60. TL;DPA
    • Types: There might be something to be gained by
    introducing gradual typing
    • Environment: There might be something to be gained
    by targeting WASM
    • Parallelism: There’s room in Ruby 3 for all kinds
    of new concurrency primitives

    View Slide

  61. View Slide

  62. Questions?
    eric_weinstein = {
    employer: 'Fox Networks Group',
    github: 'ericqweinstein',
    twitter: 'ericqweinstein',
    website: 'ericweinste.in'
    }
    30% off with RUBYCONF30! ->

    View Slide