RubyConf Argentina 2011
Upcoming SlideShare
Loading in...5
×
 

RubyConf Argentina 2011

on

  • 12,672 views

RubyConf Argentina 2011

RubyConf Argentina 2011

Statistics

Views

Total Views
12,672
Views on SlideShare
2,916
Embed Views
9,756

Actions

Likes
8
Downloads
29
Comments
0

18 Embeds 9,756

http://blog.xdite.net 9145
http://dev-xdworks.dev 266
http://feeds.feedburner.com 174
http://forum.rails-taiwan.org 82
http://www.hksilicon.com 59
http://webcache.googleusercontent.com 8
http://cache.baidu.com 5
http://news.google.com 3
http://xianguo.com 3
http://207.46.192.232 2
http://a0.twimg.com 2
http://blog.xdite.net&_=1330057888546 HTTP 1
http://chinaonrails.com 1
http://www.justaple.com 1
https://si0.twimg.com 1
http://xdite-ld.logdown.com 1
http://translate.googleusercontent.com 1
http://www.hanrss.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

RubyConf Argentina 2011 RubyConf Argentina 2011 Presentation Transcript

  • Who makes the best Asado?
  • What country has the best footballers?
  • Argentina! View slide
  • river View slide
  • riverNacional B???
  • NOOOOOOOO!!!!
  • Aaron Patterson
  • @tenderlove
  • Ruby core team
  • Rails core team
  • ! WARNING !
  • ZOMG!
  • We are in Argentina!
  • José Yo
  • WWFMD?
  • me gusta
  • ¿Por qué Maria?
  • THANKS!!
  • ResourceManagement
  • Path Management
  • Move bet ween theory and practice PatternMatching
  • Graphviz http://graphviz.org
  • greetinghello world
  • graph.dotdigraph nfa { rankdir=LR; world [shape = doublecircle]; hello [shape = circle]; hello -> world [label="greeting"];}
  • graph.dotdigraph nfa { rankdir=LR; world [shape = doublecircle]; hello [shape = circle]; goodbye [shape = circle]; hello -> world [label="greeting"]; goodbye -> world}
  • hello greeting worldgoodbye
  • /articles(.:format) / articles . (?-mix:[^./?]+)0 1 2 3 5 / new 4 6 /articles/new(.:format)
  • Journey
  • JourneyYes, its named after the 70s rock sensation
  • Provides 1: URL generation 2: Path Recognition 3: Route parsingWhat is a router?
  • Why a new router?
  • Maintenance
  • LOC300022501500 750 0 Journey Journey-2 Rack-Mount
  • Known algorithms
  • References• Compilers: Principles, Techniques, & Tools (Aho, Lam, Sethi, Ullman)• Intro to Formal Languages and Automata (Linz)
  • Predictability
  • CPU Time
  • Memory Usage
  • Current Performance rack-mount Journey url generation path recognition route parsing
  • me gusta
  • Patterns
  • Why patterns matter
  • Regular Expressions /om(g)!/
  • Rails Routes
  • resource :articles
  • /articles(.:format)/articles/new(.:format)/articles/:id/edit(.:format)/articles/:id(.:format)
  • Parens dont capture
  • :whatever => /([^./?]+)/
  • /articles(.:format)//articles(?:.([^./?]+))?$/
  • //articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  • GET /articles/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  • GET /articles/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  • GET /articles/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/ 200 OK!
  • //articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  • GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  • GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  • GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  • GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  • GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/
  • GET /foos/new//articles(?:.([^./?]+))?$///articles/new(?:.([^./?]+))?$///articles/([^./?]+)/edit(?:.([^./?]+))?$///articles/([^./?]+)(?:.([^./?]+))?$/ 404 Not Found
  • How long does this take?
  • r = routes.length
  • x = regexp compare
  • O(r ⨉ x)
  • Can we do better?
  • Parse Trees AutomataFinite State Machines
  • Parse Trees
  • Parsing regexp
  • (a|b)*abb
  • ○ Describe node types ○ b○ ba * () | a b
  • Parsing rails routes
  • Journey::Parserparser = Journey::Parser.newast = parser.parse /articles(.:format)puts ast.to_dot
  • ○ ○ ()/ articles ○ . :format
  • To String!parser = Journey::Parser.newast = parser.parse /articles(.:format)puts ast.to_sputs ast.to_regexp
  • OR ASTparser = Journey::Parser.newtrees = [ /articles(.:format), /articles/new(.:format),].map { |s| parser.parse s }ast = Journey::Nodes::Or.new treesputs ast.to_dot
  • | ○ ○ ○ () ○ ()/ articles ○ ○ new ○ . :format ○ / . :format / articles
  • SECRET FEATUREparser = Journey::Parser.newast = parser.parse /articles|books(.:format)
  • SECRET FEATUREparser = Journey::Parser.new RE T! ECast = parser.parse /articles|books(.:format) RS SU PE
  • Automata
  • (a|b)*abb
  • Double circle is acceptance state b a a b b 0 1 a a 23 b
  • baabb
  • b a a b b 0 1 a a 23 b
  • b b a a b b 0 1 a a 23 b
  • ba b a a b b 0 1 a a 23 b
  • baa b a a b b 0 1 a a 23 b
  • baabb b a a b b 0 1 a a 23 b
  • aab b a a b b 0 1 a a 23 b
  • Deterministic Finite Automaton
  • Only one path
  • 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
  • FSM Simulation
  • 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
  • move functionclass DFA ... def move(from, symbol) @table[from][symbol] endend
  • 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
  • Time: O(n) n = string.length
  • me gusta
  • Space: S + Tstates.length + transitions.length
  • NondeterministicFinite Automaton
  • Has nil edges
  • Cant tell direction
  • Simulation of NFA
  • a|b a ε 2 3 ε0 ε ε 6 b 4 5
  • nil-closure a ε 2 3 ε0 ε ε 6 b 4 5
  • a a ε 2 3 ε0 ε ε 6 b 4 5
  • 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
  • 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
  • Move functionclass NFA ... def move(states, symbol) states.map { |s| @table[s][symbol] }.flatten endend
  • 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 }=> []
  • Time: O(r ⨉ x)r = operators.length, x = string.length
  • Who cares about NFA?
  • NFA Construction
  • /articles(.:format) ○ ○ () / articles ○ . :format
  • cat nodes /0 1
  • /articles / articles0 1 2
  • Optional ε0 ε ????? ε 3 1 2
  • ε / articles0 1 2 ε ε 6 . :format 3 4 5
  • Journey::NFAparser = Journey::Parser.newast = parser.parse /articles(.:format)nfa = Journey::NFA::Builder.new asttt = nfa.transition_tableputs tt.to_dot
  • ConvertingNFA to DFA
  • Eliminate nil transitions
  • Collapse duplicate edges
  • /articles(.:format) ε / articles0 1 2 ε ε 6 . :format 3 4 5
  • /articles(.:format) / articles . :format0 1 2 3 4
  • CODES!parser = Journey::Parser.newast = parser.parse /articles(.:format)nfa = Journey::NFA::Builder.new asttt = nfa.transition_table.generalized_tableputs tt.to_dot
  • SHORTER CODES!parser = Journey::Parser.newast = parser.parse /articles(.:format)dfa = Journey::GTG::Builder.new asttt = dfa.transition_tableputs tt.to_dot
  • ANY NFAconverts to DFA
  • O(r ⨉ x) => O(x)r = operations.length, x = string.length
  • me gusta
  • Converting Automata to Regexp
  • /articles(.:format) / articles . :format0 1 2 3 4
  • /articles(.:format) /articles . :format0 2 3 4
  • /articles(.:format) /articles .:format0 2 4
  • /articles(.:format) /articles(.:format)?0 4
  • GeneralizedTransition Graph
  • resource :users/users(.:format)/users/new(.:format)/users/:id/edit(.:format)/users/:id(.:format)
  • 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
  • The Plan?
  • Combine All Routes
  • Produce DFA
  • Simulate in O(n) Time
  • Routing To The Future
  • JS Simulation
  • Table => JSONparser = Journey::Parser.newast = parser.parse /articles(.:format)dfa = Journey::GTG::Builder.new asttt = dfa.transition_tableputs tt.to_json
  • Table => SVGparser = Journey::Parser.newast = parser.parse /articles(.:format)dfa = Journey::GTG::Builder.new asttt = dfa.transition_tableputs tt.to_svg
  • JS Tokenizerfunction tokenize(input, callback) { while(input.length > 0) { callback(input.match(/^[/.?]|[^/.?]+/)[0]); input = input.replace(/^[/.?]|[^/.?]+/, ); }}
  • 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;});
  • d3.js
  • Rails Consoleirb> File.open(out.html, wb) { |f|irb* f.write(irb* Wot::Application.routes.router.visualizerirb> )}=> 69074
  • routes.rb marshalling
  • Test suggestions
  • Test coverage
  • Usage Heat Maps
  • ASTREGEXP NFA DFA
  • ROFLSCALE!!!
  • DFA => YACC
  • DFA => RACC
  • DFA => Ragel
  • Open Questions
  • Is our GTGdeterministic?
  • /users/new|/users/:id new 4 / users / (?-mix:[^./?]+)0 1 2 3 5
  • "new" =~ /new|[^./?]+/
  • Can we make itdeterministic?
  • L1 = {new}L2 = {[^./?]+}
  • /users/new|/users/:id L1 4 / users / L2 - L10 1 2 3 5
  • Is it worth our effort?
  • ASTREGEXP NFA DFA
  • Is it worth our effort?
  • Thank You!!
  • <3<3<3<3<3