Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Part 0: Hello!

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

What If...?

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

(It wasn’t.)

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

(It encourages him.)

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

== 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: -1@-1, 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)

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

($ brew uninstall ruby && brew install crystal)

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

[-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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

Part 2: What if Ruby Ran in the Browser?

Slide 36

Slide 36 text

( )

Slide 37

Slide 37 text

( )

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

It Does! (Sort Of)

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

Part 3: What if Ruby Had No GIL?

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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)

Slide 48

Slide 48 text

(Want to hear a Ruby joke?)

Slide 49

Slide 49 text

(Concurrency!)

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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#<<

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

Actors?

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

Stealing from Clojure list_of_urls.pmap(&:fetch)

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

(repeatedly #(interleave '(☕ )))

Slide 58

Slide 58 text

(Don’t encourage him.)

Slide 59

Slide 59 text

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)

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

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