RailsConf 2017

RailsConf 2017

It's my keynote from RailsConf 2017

F29327647a9cff5c69618bae420792ea?s=128

Aaron Patterson

May 05, 2017
Tweet

Transcript

  1. None
  2. Hello ICON!

  3. Hello RailsConf!

  4. None
  5. Hi, I’m @tenderlove

  6. None
  7. h GitHub

  8. Le Git

  9. Le Gîte Hub

  10. Rails Core Team

  11. Ruby Core Team

  12. None
  13. None
  14. None
  15. I have stickers!

  16. None
  17. None
  18. None
  19. None
  20. "Why Slack is inappropriate for open source communications"

  21. "We are, temporarily, in a kind of dark ages of

    end-user open source software."
  22. Oops, I died of plague This is a rat

  23. Electron is flash for the desktop

  24. "slack often idles at 5% CPU usage"

  25. CPU Slack

  26. "Buy a bigger CPU, ya dummy"

  27. Alan Turning

  28. HN on Language Features

  29. "No generics and no sum types? Those are no longer

    groundbreaking, they're the bare minimum.*" *Emphasis not mine
  30. No generics means your language is a failure

  31. Insurance companies only cover Generics

  32. Sorry, your language has been denied L'Hôpital

  33. None
  34. None
  35. #supportlocal

  36. Local Coffee!

  37. Local Tea!

  38. Trolling DHH: An Annual Tradition

  39. None
  40. None
  41. Faith Based Programmer

  42. "Pleaseworkpleaseworkpleas eworkpleaseworkpleasework" The Programmer’s Prayer

  43. None
  44. None
  45. 24 bit audio

  46. 10+ Years of Rails

  47. It was the year 2003

  48. None
  49. What should I do with all this free time?

  50. "We’ve tried to charge your card hundreds of times"

  51. Technical Debt

  52. Developers want to pay off technical debt

  53. Managers do not want to pay off technical debt (if

    they can help it)
  54. Tech Debt Gem Gem Gem Gem Gem Meta Gem

  55. Tech Debt Gem Gem Gem Gem Gem "Bond" "Tranche"

  56. Tech Debt Gem Gem Gem Webpack Gem Rails

  57. Blood of young people

  58. Concatenating a bunch of strings

  59. None
  60. None
  61. None
  62. Not a Joke

  63. 5

  64. 5

  65. $5

  66. None
  67. 5.1

  68. Rails 5.1 is out!

  69. Thanks @rafaelfranca!!! ❤

  70. I don’t have time for this Things I don’t have

    time for but would like to do
  71. Non-committal

  72. Humorous use of common phrase

  73. "No Pressure"

  74. ALL OF THE PRESSURE

  75. Searls - Briggs

  76. STRESS

  77. Fear & Self Doubt

  78. 5 things I don’t have time to do but you

    should do them for me
  79. What if I don’t have time to present 5 things??

  80. What if I want to talk about things I do

    have time for?
  81. Some things I don’t have time to do but you

    should do them for me Maybe like 3 things?
  82. Probably Important Definitely Not Important

  83. HTTP/2 + Rack A thing that I do have time

    for
  84. What is HTTP/2?

  85. 1 better than HTTP/1

  86. 0.9 better than HTTP/1.1

  87. HTTP/2 (really) • Binary protocol • Multiplexes (multiple requests on

    the same socket) • Secure (only works over SSL*) • Push responses
  88. Push Response Flow

  89. HTTP 1.1 Time index.html jquery.js gorby.css Client Server

  90. HTTP 2 Time index.html jquery.js gorby.css Client Server

  91. Save Time by Pushing "Needed" Resources

  92. H2 Problems

  93. H2 is still stateless

  94. HTTP 2 Time index.html jquery.js gorby.css Client Server

  95. Double Assets • Client can cancel (requires round trip) •

    Resend assets (extra bandwidth)
  96. Solution: H2O + SALT Get it, "solution"????

  97. Solution: H2O + Cookies

  98. What is H2O? https://h2o.examp1e.net

  99. Server (Unicorn) Proxy (h2o) Client HTTP/2 HTTP/1.1

  100. H2 Pushes with HTTP/1.1

  101. Link Header 200 OK Content-Length: 1024 Content-Type: text/html Link: </choochoo.css>;

    rel=preload Link: </gorby.js>; rel=preload response body
  102. Server (Unicorn) Proxy (h2o) Client HTTP/2 HTTP/1.1 200 OK Content-Length:

    1024 Content-Type: text/html Link: </choochoo.css>; rel=preload Link: </gorby.js>; rel=preload response body
  103. No state tracking in the app

  104. Link Header Problem 200 OK Content-Length: 1024 Content-Type: text/html Link:

    </choochoo.css>; rel=preload Link: </gorby.js>; rel=preload response body
  105. 103 Early Hints

  106. 103 Early Response 103 Early Hints Link: </choochoo.css>; rel=preload Link:

    </gorby.js>; rel=preload 200 OK Content-Length: 1024 Content-Type: text/html response body
  107. Rack Support Rack 3.0

  108. New ENV hash key! ("yay") env['rack.push'].call(103, [ ['Link', '/gorby.css'] ],

    [])
  109. Backwards Compatibility

  110. Graceful Upgrade

  111. Rack 3.0

  112. This is a talk about code smells

  113. Data I acquired (crap data) -100 925 1950 2975 4000

    Time 2017-01-23 15:53:51 2017-01-23 15:53:56 2017-01-23 15:54:01 2017-01-23 15:54:06 2017-01-23 15:54:11 2017-01-23 15:54:16 2017-01-23 15:54:21 2017-01-23 15:54:26 2017-01-23 15:54:31 2017-01-23 15:54:37 2017-01-23 15:54:42 2017-01-23 15:54:47 2017-01-23 15:54:52 2017-01-23 15:54:57 2017-01-23 15:55:02 2017-01-23 15:55:07 2017-01-23 15:55:12 2017-01-23 15:55:17 2017-01-23 15:55:22 2017-01-23 15:55:27 2017-01-23 15:55:32
  114. Ruby VM Tricks

  115. How a VM works

  116. VM [push, 4] [push, 3] [add] PC Program Stack 4

    3 7
  117. Implementation instructions = [ [:push, 3], [:push, 7], [:add], ]

    pc = 0 loop do instruction = instructions[pc] pc += 1 send function_table[instruction.first] end
  118. Generate the VM

  119. Loop Elimination instructions = [ [:push, 3], [:push, 7], [:add],

    ] def push_op pc, val, instructions # code to push on the stack # .... next_instruction = instructions[pc] send(function_table[next_instruction.first] pc + 1, next_instruction, instructions) end def add pc, val, instructions # code to add # .... next_instruction = instructions[pc] send(function_table[next_instruction.first] pc + 1, next_instruction, instructions) end # start of VM pc = 0 instruction = instructions[pc] pc += 1 send function_table[instruction.first] Generated
  120. Threaded VM

  121. Function call elimination

  122. Function Name Lookup Table instructions = [ [:push, 3], [:push,

    7], [:add], ] function_table = { :push => :push_op, :add => :add_op, } def push_op pc, val, instructions # code to push on the stack # .... next_instruction = instructions[pc] send(function_table[next_instruction.first] pc + 1, next_instruction, instructions) end
  123. JUMP instructions = [ [:push, 3], [:push, 7], [:add], ]

    function_table = { :push => ADDRESS_OF(:push_op), :add => ADDRESS_OF(:add_op), } label: :add_op # code to add # ... next_instruction = instructions[pc] val = next_instruction.drop(1) address = function_table[next_instruction.first] pc += 1 GOTO(address) label: :push_op # code to push on the stack # .... next_instruction = instructions[pc] val = next_instruction.drop(1) address = function_table[next_instruction.first] pc += 1 GOTO(address) Generated
  124. Lookup Table Elimination

  125. Addresses in Byte Code instructions = [ [ADDRESS_OF(:push_op), 3], [ADDRESS_OF(:push_op),

    7], [ADDRESS_OF(:add)], ] label: :add_op # code to add # ... next_instruction = instructions[pc] val = next_instruction.drop(1) address = next_instruction.first pc += 1 GOTO(address) label: :push_op # code to push on the stack # .... next_instruction = instructions[pc] val = next_instruction.drop(1) address = next_instruction.first pc += 1 GOTO(address)
  126. Direct Threaded VM

  127. Addresses are just integers

  128. MRI’s VM is Direct Threaded

  129. Create custom instructions built from machine code at runtime

  130. Extremely Simple Code require 'lolvm' class MyRuby attr_reader :rb_path2class, :rb_define_method,

    :mod def initialize ctx @mod = ctx.create_module 'ruby' @ctx = ctx init_functions end private def init_functions @rb_path2class = make_func('rb_path2class', @ctx.int8.pointer, [@ctx.int8.pointer]) @rb_define_method = make_func('rb_define_method', @ctx.int8.pointer, [@ctx.int8.pointer, @ctx.int8.pointer, @ctx.int8.pointer, @ctx.int32]) end def make_func name, ret, args func_type = LOLVM::Types::Function.new(ret, args, false) @mod.add_function name, func_type end end context = LOLVM::Context.instance builder = context.create_builder ruby = MyRuby.new context mod = context.create_module 'anon mod' func_type = LOLVM::Types::Function.new(context.double, [], false) testing = mod.add_function "testing", LOLVM::Types::Function.new(context.int64, [context.int8.pointer], false) testing.param(0).name = "foo" bb = context.append_basic_block testing, "entry" x = mod.add_global context.int64, 'rb_cObject' x.linkage = LOLVM::Linkages::External builder.position_at_end_of bb builder.ret builder.load x, "obj" func = mod.add_function "__anon", func_type bb = context.append_basic_block func, "entry" builder.position_at_end_of bb str = builder.global_string "MyRuby", 'string' func_name = builder.global_string "testing", 'func_name' my_ruby = builder.call testing, [str], 'rb_str' builder.ret my_ruby ee = mod.execution_engine ee.add_module ruby.mod p :GOT => ee.run("__anon") Assembles machine code at run time using LLVM
  131. Idea 1: Custom Instructions at Runtime

  132. Data I acquired (crap data) -100 925 1950 2975 4000

    Time 2017-01-23 15:53:51 2017-01-23 15:53:56 2017-01-23 15:54:01 2017-01-23 15:54:06 2017-01-23 15:54:11 2017-01-23 15:54:16 2017-01-23 15:54:21 2017-01-23 15:54:26 2017-01-23 15:54:31 2017-01-23 15:54:37 2017-01-23 15:54:42 2017-01-23 15:54:47 2017-01-23 15:54:52 2017-01-23 15:54:57 2017-01-23 15:55:02 2017-01-23 15:55:07 2017-01-23 15:55:12 2017-01-23 15:55:17 2017-01-23 15:55:22 2017-01-23 15:55:27 2017-01-23 15:55:32
  133. Build a Police Scanner

  134. None
  135. Software Defined Radio

  136. None
  137. FM Band

  138. Narrow FM Digital Trunking signal Audio

  139. Digital Signal Processing

  140. Continuous / Discrete Very Discrete tenderlove

  141. Discrete signals are just a list of points

  142. Discrete Signal (crap data) -100 925 1950 2975 4000 Time

    2017-01-23 15:53:51 2017-01-23 15:53:56 2017-01-23 15:54:01 2017-01-23 15:54:06 2017-01-23 15:54:11 2017-01-23 15:54:16 2017-01-23 15:54:21 2017-01-23 15:54:26 2017-01-23 15:54:31 2017-01-23 15:54:37 2017-01-23 15:54:42 2017-01-23 15:54:47 2017-01-23 15:54:52 2017-01-23 15:54:57 2017-01-23 15:55:02 2017-01-23 15:55:07 2017-01-23 15:55:12 2017-01-23 15:55:17 2017-01-23 15:55:22 2017-01-23 15:55:27 2017-01-23 15:55:32
  143. Convolution

  144. Signal Convolution -100 925 1950 2975 4000 Time 2017-01-23 15:53:51

    2017-01-23 15:54:01 2017-01-23 15:54:11 2017-01-23 15:54:21 2017-01-23 15:54:31 2017-01-23 15:54:42 2017-01-23 15:54:52 2017-01-23 15:55:02 2017-01-23 15:55:12 2017-01-23 15:55:22 2017-01-23 15:55:32 0 0.25 0.5 0.75 1 0 1 2 3 4 5 6 7 * =?
  145. Formal Definition

  146. X -1.5 -0.5 0.5 1.5 0 1 2 3 4

    5 6 7 8 H -0.5 0 0.5 1 3 2 1 0 Y -1.5 0 1.5 3 0 1 2 3 4 5 6 7 8 9 10 11
  147. Convolution Code def convolve x, h Array.new(x.length + h.length -

    1) do |i| h.map.with_index { |h_j, j| if i - j < 0 || i - j > x.length - 1 0 else h_j * x[i - j] end }.inject(:+) end end
  148. Convolved Signal Length: x.length + h.length - 1

  149. X -1.5 -0.5 0.5 1.5 0 1 2 3 4

    5 6 7 8 H -0.5 0 0.5 1 3 2 1 0 x + y[i] value
  150. Low Pass Filters

  151. Identity Signal X -1.5 -0.5 0.5 1.5 0 1 2

    3 4 5 6 7 8 H 0 0.25 0.5 0.75 1 0 1 2 3 * = Y -1.5 -0.5 0.5 1.5 0 1 2 3 4 5 6 7 8 9 10 11
  152. Amplifier X -1.5 -0.5 0.5 1.5 0 1 2 3

    4 5 6 7 8 H 0 0.5 1 1.5 2 0 1 2 3 * = Y -3 -1 1 3 0 2 4 6 8 10
  153. Shift X -1.5 -0.5 0.5 1.5 0 1 2 3

    4 5 6 7 8 H 0 0.25 0.5 0.75 1 0 1 2 3 * = Y -1.5 -0.5 0.5 1.5 0 1 2 3 4 5 6 7 8 9 10 11
  154. Echo X -1.5 -0.5 0.5 1.5 0 1 2 3

    4 5 6 7 8 H 0 0.5 1 1.5 2 0 1 2 3 * = Y -3.75 -1.25 1.25 3.75 0 1 2 3 4 5 6 7 8 9 10 11
  155. Average X -1.5 -0.5 0.5 1.5 0 1 2 3

    4 5 6 7 8 H 0 0.25 0.5 0.75 1 0 1 2 3 * H 0 0.125 0.25 0.375 0.5 0 1 2 3 *
  156. Radar

  157. Radar Transmission 0 25 50 75 100 Reception -25 0

    25 50 75 100
  158. Does one signal contain the other?

  159. received * transmitted Detection -10000 0 10000 20000 30000 40000

  160. Gaussian Distribution

  161. Self Convolution signal = 100.times.map { rand } 3.times do

    signal = convolve signal, signal end
  162. Self Convolution Gaussian Distribution 0 75000000000 150000000000 225000000000 300000000000 Neat!

    tenderlove
  163. Convolution Code def convolve x, h Array.new(x.length + h.length -

    1) do |i| h.map.with_index { |h_j, j| if i - j < 0 || i - j > x.length - 1 0 else h_j * x[i - j] end }.inject(:+) end end
  164. My Signal

  165. R, the hard way

  166. Arrays are 1 based > data <- c(4, 3, 2,

    1) > data[0] numeric(0) > data[0] + 1 numeric(0) >
  167. There must be an easier way! tenderlove

  168. Data I acquired (crap data) -100 925 1950 2975 4000

    Time 2017-01-23 15:53:51 2017-01-23 15:53:56 2017-01-23 15:54:01 2017-01-23 15:54:06 2017-01-23 15:54:11 2017-01-23 15:54:16 2017-01-23 15:54:21 2017-01-23 15:54:26 2017-01-23 15:54:31 2017-01-23 15:54:37 2017-01-23 15:54:42 2017-01-23 15:54:47 2017-01-23 15:54:52 2017-01-23 15:54:57 2017-01-23 15:55:02 2017-01-23 15:55:07 2017-01-23 15:55:12 2017-01-23 15:55:17 2017-01-23 15:55:22 2017-01-23 15:55:27 2017-01-23 15:55:32
  169. Implementing cons, car, and cdr in many languages (using only

    lambdas)
  170. Why?

  171. I like learning new languages

  172. But I don’t have much time

  173. Bare minimum to get endorsed on Linked In Do people

    still use Klout?
  174. What are cons, car, and cdr?

  175. cons forms a cell L R

  176. car returns the left side L R

  177. cdr returns the right side L R

  178. Only Lambdas?

  179. cons tenderlove.cons <- function(x, y) { function(m) { m(x, y)

    } } R Node cons = ->(x, y) { ->(m) { m.(x, y) } } Ruby var cons = function(x, y) { return function(m) { return m(x, y); }; }
  180. car tenderlove.car <- function(z) { z(function(p, q) { p })

    } R var car = function(z) { return z(function(p, q) { return p; }); } Node car = ->(z) { z.(->(p, q) { p }) } Ruby
  181. Usage > tenderlove.cons(1, 2) function(m) { m(x, y) } <environment:

    0x7f8c55961f80> > tenderlove.car function(z) { z(function(p, q) { p }) } > tenderlove.car(tenderlove.cons(1, 2)) [1] 1 >
  182. cdr tenderlove.cdr <- function(z) { z(function(p, q) { q })

    } R var cdr = function(z) { return z(function(p, q) { return q; }); } Node cdr = ->(z) { z.(->(p, q) { q }) } Ruby
  183. Tree of Cells 1 2 3 NUL

  184. each tenderlove.each <- function(func, lst) { if (!is.null(lst)) { element

    <- tenderlove.car(lst) func(element) tenderlove.each(func, tenderlove.cdr(lst)) } } R Node each = ->(func, list) { if list element = car.(list) func.(element) each.(func, cdr.(list)) end } Ruby var each = function(func, list) { if(list) { element = car(list); func(element); each(func, cdr(list)); } }
  185. Usage var each = function(func, list) { if(list) { element

    = car(list); func(element); each(func, cdr(list)); } } each(console.log, cons(1, (cons(2, cons(3, null))))); [aaron@TC dsp (master)]$ node dsp.js 1 2 3 [aaron@TC dsp (master)]$
  186. Don’t need loops

  187. Don’t need arrays

  188. Don’t need hashes

  189. Numbers?

  190. Numbers tenderlove.zero <- function(f) { function(x) { x } }

    tenderlove.one <- function(f) { function(x) { f(x) } } tenderlove.two <- function(f) { function(x) { f(f(x)) } } tenderlove.three <- function(f) { function(x) { f(f(f(x))) } } print(tenderlove.three(function(x) { x + 1 })(0)) => 3
  191. Addition tenderlove.one <- function(f) { function(x) { f(x) } }

    tenderlove.add <- function(a, b) { function(f) { function(x) { a(f)(b(f)(x)) } } } tenderlove.two <- tenderlove.add(tenderlove.one, tenderlove.one) tenderlove.three <- tenderlove.add(tenderlove.one, tenderlove.two) print(tenderlove.three(function(x) { x + 1 })(0)) # => 3
  192. Church Encoding

  193. Don’t need Numbers

  194. Don’t need Mathematics

  195. Logic?

  196. true / false / if True = ->(x, y) {

    x } False = ->(x, y) { y } If = ->(cond, t, f) { cond.(t, f) } If.(True, ->() { :true }, ->() { :false }).call # => :true If.(False, ->() { :true }, ->() { :false }).call # => :false
  197. Don’t need booleans

  198. Don’t need conditionals

  199. My Signal (crap data) -100 925 1950 2975 4000 Time

    2017-01-23 15:53:51 2017-01-23 15:53:56 2017-01-23 15:54:01 2017-01-23 15:54:06 2017-01-23 15:54:11 2017-01-23 15:54:16 2017-01-23 15:54:21 2017-01-23 15:54:26 2017-01-23 15:54:31 2017-01-23 15:54:37 2017-01-23 15:54:42 2017-01-23 15:54:47 2017-01-23 15:54:52 2017-01-23 15:54:57 2017-01-23 15:55:02 2017-01-23 15:55:07 2017-01-23 15:55:12 2017-01-23 15:55:17 2017-01-23 15:55:22 2017-01-23 15:55:27 2017-01-23 15:55:32
  200. cons / car / cdr / each tenderlove.cons <- function(x,

    y) { function(m) { m(x, y) } } tenderlove.car <- function(z) { z(function(p, q) { p }) } tenderlove.cdr <- function(z) { z(function(p, q) { q }) } tenderlove.each <- function(func, lst) { if (!is.null(lst)) { element <- tenderlove.car(lst) func(element) tenderlove.each(func, tenderlove.cdr(lst)) } } tenderlove.each_with_index <- function(func, lst) { idx <- 0 tenderlove.each(function(element) { func(idx, element) idx = idx + 1 }, lst) }
  201. array indexing tenderlove.vec_at <- function(idx, lst) { if(idx == 0)

    { tenderlove.car(lst) } else { tenderlove.vec_at(idx - 1, tenderlove.cdr(lst)) } }
  202. Converting Vectors to cons tenderlove.c2cons <- function(cs) { foldl <-

    function(proc, init, lst) { if(length(lst) == 0) { init } else { foldl(proc, proc(head(lst, 1), init), tail(lst, -1)) } } foldl(tenderlove.cons, NULL, rev(cs)) }
  203. Convolution in R tenderlove.conv <- function(x, h) { x_list <-

    tenderlove.c2cons(x) h_list <- tenderlove.c2cons(h) indexes <- 0:(length(x) + length(h) - 1) sapply(indexes, function(i) { sum(tenderlove.cons2c(tenderlove.map_with_index(function(j, h_j) { if (i - j < 0 || i - j > length(x) - 1) { 0 } else { h_j * tenderlove.vec_at(i - j, x_list) } }, h_list))) }) }
  204. Feed in test data > data <- c(0, -1, -1.2,

    2, 1.5, 1.4, 0.5, 0, -0.5) > plot(data) > filter <- c(2, 0, 1) > plot(filter) > plot(tenderlove.conv(data, filter))
  205. * = Nice. tenderlove

  206. Input Real Data > plot(tenderlove.conv(unlist(dat$V2), c(1))) Error: evaluation nested too

    deeply: infinite recursion / options(expressions=)? I f#$@*ing hate R. tenderlove
  207. Things I don’t have time for: Figuring out R.

  208. My Signal (crap data) -100 925 1950 2975 4000 Time

    2017-01-23 15:53:51 2017-01-23 15:53:56 2017-01-23 15:54:01 2017-01-23 15:54:06 2017-01-23 15:54:11 2017-01-23 15:54:16 2017-01-23 15:54:21 2017-01-23 15:54:26 2017-01-23 15:54:31 2017-01-23 15:54:37 2017-01-23 15:54:42 2017-01-23 15:54:47 2017-01-23 15:54:52 2017-01-23 15:54:57 2017-01-23 15:55:02 2017-01-23 15:55:07 2017-01-23 15:55:12 2017-01-23 15:55:17 2017-01-23 15:55:22 2017-01-23 15:55:27 2017-01-23 15:55:32
  209. Something I built

  210. None
  211. Bathroom Scale

  212. msp430

  213. Raspberry Pi + Motion Sensor

  214. Litter Box

  215. I made this Weight (g) -100 925 1950 2975 4000

    Time 2017-01-23 15:53:51 2017-01-23 15:53:56 2017-01-23 15:54:01 2017-01-23 15:54:06 2017-01-23 15:54:11 2017-01-23 15:54:16 2017-01-23 15:54:21 2017-01-23 15:54:26 2017-01-23 15:54:31 2017-01-23 15:54:37 2017-01-23 15:54:42 2017-01-23 15:54:47 2017-01-23 15:54:52 2017-01-23 15:54:57 2017-01-23 15:55:02 2017-01-23 15:55:07 2017-01-23 15:55:12 2017-01-23 15:55:17 2017-01-23 15:55:22 2017-01-23 15:55:27 2017-01-23 15:55:32 Cat Enters Cat Leaves
  216. ~100g

  217. Wrap-Up

  218. It’s hard to make shit scale I told you those

    graphs were crap