RubyConf Argentina 2011

13,156
-1

Published on

RubyConf Argentina 2011

Published in: Technology, Business

RubyConf Argentina 2011

  1. 1. Who makes the best Asado?
  2. 2. What country has the best footballers?
  3. 3. Argentina!
  4. 4. river
  5. 5. riverNacional B???
  6. 6. NOOOOOOOO!!!!
  7. 7. Aaron Patterson
  8. 8. @tenderlove
  9. 9. Ruby core team
  10. 10. Rails core team
  11. 11. ! WARNING !
  12. 12. ZOMG!
  13. 13. We are in Argentina!
  14. 14. José Yo
  15. 15. WWFMD?
  16. 16. me gusta
  17. 17. ¿Por qué Maria?
  18. 18. THANKS!!
  19. 19. ResourceManagement
  20. 20. Path Management
  21. 21. Move bet ween theory and practice PatternMatching
  22. 22. Graphviz http://graphviz.org
  23. 23. greetinghello world
  24. 24. graph.dotdigraph nfa { rankdir=LR; world [shape = doublecircle]; hello [shape = circle]; hello -> world [label="greeting"];}
  25. 25. graph.dotdigraph nfa { rankdir=LR; world [shape = doublecircle]; hello [shape = circle]; goodbye [shape = circle]; hello -> world [label="greeting"]; goodbye -> world}
  26. 26. hello greeting worldgoodbye
  27. 27. /articles(.:format) / articles . (?-mix:[^./?]+)0 1 2 3 5 / new 4 6 /articles/new(.:format)
  28. 28. Journey
  29. 29. JourneyYes, its named after the 70s rock sensation
  30. 30. Provides 1: URL generation 2: Path Recognition 3: Route parsingWhat is a router?
  31. 31. Why a new router?
  32. 32. Maintenance
  33. 33. LOC300022501500 750 0 Journey Journey-2 Rack-Mount
  34. 34. Known algorithms
  35. 35. References• Compilers: Principles, Techniques, & Tools (Aho, Lam, Sethi, Ullman)• Intro to Formal Languages and Automata (Linz)
  36. 36. Predictability
  37. 37. CPU Time
  38. 38. Memory Usage
  39. 39. Current Performance rack-mount Journey url generation path recognition route parsing
  40. 40. me gusta
  41. 41. Patterns
  42. 42. Why patterns matter
  43. 43. Regular Expressions /om(g)!/
  44. 44. Rails Routes
  45. 45. resource :articles
  46. 46. /articles(.:format)/articles/new(.:format)/articles/:id/edit(.:format)/articles/:id(.:format)
  47. 47. Parens dont capture
  48. 48. :whatever => /([^./?]+)/
  49. 49. /articles(.:format)//articles(?:.([^./?]+))?$/
  50. 50. //articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  51. 51. GET /articles/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  52. 52. GET /articles/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  53. 53. GET /articles/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/ 200 OK!
  54. 54. //articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  55. 55. GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  56. 56. GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  57. 57. GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  58. 58. GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  59. 59. GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  60. 60. GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/ 404 Not Found
  61. 61. How long does this take?
  62. 62. r = routes.length
  63. 63. x = regexp compare
  64. 64. O(r ⨉ x)
  65. 65. Can we do better?
  66. 66. Parse Trees AutomataFinite State Machines
  67. 67. Parse Trees
  68. 68. Parsing regexp
  69. 69. (a|b)*abb
  70. 70. ○ Describe node types ○ b○ ba * () | a b
  71. 71. Parsing rails routes
  72. 72. Journey::Parserparser = Journey::Parser.newast = parser.parse /articles(.:format)puts ast.to_dot
  73. 73. ○ ○ ()/ articles ○ . :format
  74. 74. To String!parser = Journey::Parser.newast = parser.parse /articles(.:format)puts ast.to_sputs ast.to_regexp
  75. 75. OR ASTparser = Journey::Parser.newtrees = [ /articles(.:format), /articles/new(.:format),].map { |s| parser.parse s }ast = Journey::Nodes::Or.new treesputs ast.to_dot
  76. 76. | ○ ○ ○ () ○ ()/ articles ○ ○ new ○ . :format ○ / . :format / articles
  77. 77. SECRET FEATUREparser = Journey::Parser.newast = parser.parse /articles|books(.:format)
  78. 78. SECRET FEATUREparser = Journey::Parser.new RE T! ECast = parser.parse /articles|books(.:format) RS SU PE
  79. 79. Automata
  80. 80. (a|b)*abb
  81. 81. Double circle is acceptance state b a a b b 0 1 a a 23 b
  82. 82. baabb
  83. 83. b a a b b 0 1 a a 23 b
  84. 84. b b a a b b 0 1 a a 23 b
  85. 85. ba b a a b b 0 1 a a 23 b
  86. 86. baa b a a b b 0 1 a a 23 b
  87. 87. baabb b a a b b 0 1 a a 23 b
  88. 88. aab b a a b b 0 1 a a 23 b
  89. 89. Deterministic Finite Automaton
  90. 90. Only one path
  91. 91. Storageclass DFA attr_reader :table def initialize @table = Hash.new { |h, from| h[from] = {} } @table[0][a] = 1 @table[0][b] = 0 @table[1][a] = 1 @table[1][b] = 2 @table[2][a] = 1 @table[2][b] = 3 @table[3][b] = 0 @table[3][a] = 2 endend
  92. 92. FSM Simulation
  93. 93. class Simulator def initialize(dfa) @dfa = dfa end def simulate(symbols) state = 0 until symbols.empty? state = @dfa.move(state, symbols.shift) end state endend
  94. 94. move functionclass DFA ... def move(from, symbol) @table[from][symbol] endend
  95. 95. irb> sim = Simulator.new(DFA.new)=> #<Simulator:0x007f95929a82e0 ...>irb> sim.simulate %w{ b a a b b }=> 3irb> sim.simulate %w{ a a b }=> 2
  96. 96. Time: O(n) n = string.length
  97. 97. me gusta
  98. 98. Space: S + Tstates.length + transitions.length
  99. 99. NondeterministicFinite Automaton
  100. 100. Has nil edges
  101. 101. Cant tell direction
  102. 102. Simulation of NFA
  103. 103. a|b a ε 2 3 ε0 ε ε 6 b 4 5
  104. 104. nil-closure a ε 2 3 ε0 ε ε 6 b 4 5
  105. 105. a a ε 2 3 ε0 ε ε 6 b 4 5
  106. 106. Storageclass NFA def initialize @table = Hash.new { |h, from| h[from] = Hash.new { |i,sym| i[sym] = [] } } @table[0][nil] << 2 @table[0][nil] << 4 @table[2][a] << 3 @table[4][b] << 5 @table[3][nil] << 6 @table[5][nil] << 6 end def nil_closure(states) states.map { |s| @table[s][nil] }.flatten endend
  107. 107. FSM Simulationclass Simulator def initialize(nfa) @nfa = nfa end def simulate(symbols) states = @nfa.nil_closure([0]) until symbols.empty? next_s = @nfa.move(states, symbols.shift) states = @nfa.nil_closure(next_s) end states endend
  108. 108. Move functionclass NFA ... def move(states, symbol) states.map { |s| @table[s][symbol] }.flatten endend
  109. 109. irb> sim = Simulator.new(NFA.new)=> #<Simulator:0x007faa188a5f88 ...>irb> sim.simulate %w{ a }=> [6]irb> sim.simulate %w{ b }=> [6]irb> sim.simulate %w{ b b }=> []irb> sim.simulate %w{ c }=> []
  110. 110. Time: O(r ⨉ x)r = operators.length, x = string.length
  111. 111. Who cares about NFA?
  112. 112. NFA Construction
  113. 113. /articles(.:format) ○ ○ () / articles ○ . :format
  114. 114. cat nodes /0 1
  115. 115. /articles / articles0 1 2
  116. 116. Optional ε0 ε ????? ε 3 1 2
  117. 117. ε / articles0 1 2 ε ε 6 . :format 3 4 5
  118. 118. Journey::NFAparser = Journey::Parser.newast = parser.parse /articles(.:format)nfa = Journey::NFA::Builder.new asttt = nfa.transition_tableputs tt.to_dot
  119. 119. ConvertingNFA to DFA
  120. 120. Eliminate nil transitions
  121. 121. Collapse duplicate edges
  122. 122. /articles(.:format) ε / articles0 1 2 ε ε 6 . :format 3 4 5
  123. 123. /articles(.:format) / articles . :format0 1 2 3 4
  124. 124. CODES!parser = Journey::Parser.newast = parser.parse /articles(.:format)nfa = Journey::NFA::Builder.new asttt = nfa.transition_table.generalized_tableputs tt.to_dot
  125. 125. SHORTER CODES!parser = Journey::Parser.newast = parser.parse /articles(.:format)dfa = Journey::GTG::Builder.new asttt = dfa.transition_tableputs tt.to_dot
  126. 126. ANY NFAconverts to DFA
  127. 127. O(r ⨉ x) => O(x)r = operations.length, x = string.length
  128. 128. me gusta
  129. 129. Converting Automata to Regexp
  130. 130. /articles(.:format) / articles . :format0 1 2 3 4
  131. 131. /articles(.:format) /articles . :format0 2 3 4
  132. 132. /articles(.:format) /articles .:format0 2 4
  133. 133. /articles(.:format) /articles(.:format)?0 4
  134. 134. GeneralizedTransition Graph
  135. 135. resource :users/users(.:format)/users/new(.:format)/users/:id/edit(.:format)/users/:id(.:format)
  136. 136. resource :users (?-mix:[^./?]+) . 3 5 / users0 1 2 / new . (?-mix:[^./?]+) 4 6 8 11 (?-mix:[^./?]+) / edit . (?-mix:[^./?]+) 7 9 12 14 15 . (?-mix:[^./?]+) 10 13
  137. 137. The Plan?
  138. 138. Combine All Routes
  139. 139. Produce DFA
  140. 140. Simulate in O(n) Time
  141. 141. Routing To The Future
  142. 142. JS Simulation
  143. 143. Table => JSONparser = Journey::Parser.newast = parser.parse /articles(.:format)dfa = Journey::GTG::Builder.new asttt = dfa.transition_tableputs tt.to_json
  144. 144. Table => SVGparser = Journey::Parser.newast = parser.parse /articles(.:format)dfa = Journey::GTG::Builder.new asttt = dfa.transition_tableputs tt.to_svg
  145. 145. JS Tokenizerfunction tokenize(input, callback) { while(input.length > 0) { callback(input.match(/^[/.?]|[^/.?]+/)[0]); input = input.replace(/^[/.?]|[^/.?]+/, ); }}
  146. 146. JS Simulatortokenize(input, function(token) { var new_states = []; for(var key in states) { var state = states[key]; if(string_states[state] && string_states[state][token]) { var new_state = string_states[state][token]; highlight_edge(state, new_state); highlight_state(new_state); new_states.push(new_state); } } if(new_states.length == 0) { return; } states = new_states;});
  147. 147. d3.js
  148. 148. Rails Consoleirb> File.open(out.html, wb) { |f|irb* f.write(irb* Wot::Application.routes.router.visualizerirb> )}=> 69074
  149. 149. routes.rb marshalling
  150. 150. Test suggestions
  151. 151. Test coverage
  152. 152. Usage Heat Maps
  153. 153. ASTREGEXP NFA DFA
  154. 154. ROFLSCALE!!!
  155. 155. DFA => YACC
  156. 156. DFA => RACC
  157. 157. DFA => Ragel
  158. 158. Open Questions
  159. 159. Is our GTGdeterministic?
  160. 160. /users/new|/users/:id new 4 / users / (?-mix:[^./?]+)0 1 2 3 5
  161. 161. "new" =~ /new|[^./?]+/
  162. 162. Can we make itdeterministic?
  163. 163. L1 = {new}L2 = {[^./?]+}
  164. 164. /users/new|/users/:id L1 4 / users / L2 - L10 1 2 3 5
  165. 165. Is it worth our effort?
  166. 166. ASTREGEXP NFA DFA
  167. 167. Is it worth our effort?
  168. 168. Thank You!!
  169. 169. <3<3<3<3<3
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×