+ All Categories
Home > Technology > RubyConf Argentina 2011

RubyConf Argentina 2011

Date post: 29-Jun-2015
Category:
Upload: aaron-patterson
View: 12,773 times
Download: 3 times
Share this document with a friend
Description:
RubyConf Argentina 2011
Popular Tags:
180
Who makes the best Asado?
Transcript
Page 1: RubyConf Argentina 2011

Who makes the best Asado?

Page 2: RubyConf Argentina 2011
Page 3: RubyConf Argentina 2011
Page 4: RubyConf Argentina 2011
Page 5: RubyConf Argentina 2011
Page 6: RubyConf Argentina 2011
Page 7: RubyConf Argentina 2011
Page 8: RubyConf Argentina 2011

What country has the best footballers?

Page 9: RubyConf Argentina 2011
Page 10: RubyConf Argentina 2011

Argentina!

Page 11: RubyConf Argentina 2011

river

Page 12: RubyConf Argentina 2011

Nacional B???

river

Page 13: RubyConf Argentina 2011
Page 14: RubyConf Argentina 2011

NOOOOOOOO!!!!

Page 15: RubyConf Argentina 2011

Aaron Patterson

Page 16: RubyConf Argentina 2011

@tenderlove

Page 17: RubyConf Argentina 2011

Ruby core team

Page 18: RubyConf Argentina 2011

Rails core team

Page 19: RubyConf Argentina 2011

! WARNING !

Page 20: RubyConf Argentina 2011

ZOMG!

Page 21: RubyConf Argentina 2011

We are in Argentina!

Page 22: RubyConf Argentina 2011
Page 23: RubyConf Argentina 2011

YoJosé

Page 24: RubyConf Argentina 2011

WWFMD?

Page 25: RubyConf Argentina 2011

me gusta

Page 26: RubyConf Argentina 2011

¿Por qué Maria?

Page 27: RubyConf Argentina 2011

THANKS!!

Page 28: RubyConf Argentina 2011
Page 29: RubyConf Argentina 2011

ResourceManagement

Page 30: RubyConf Argentina 2011

Path Management

Page 31: RubyConf Argentina 2011

PatternMatching

Move between theory and practice

Page 32: RubyConf Argentina 2011

Graphvizhttp://graphviz.org

Page 33: RubyConf Argentina 2011

worldhello greeting

Page 34: RubyConf Argentina 2011

digraph nfa { rankdir=LR;

world [shape = doublecircle]; hello [shape = circle]; hello -> world [label="greeting"];}

graph.dot

Page 35: RubyConf Argentina 2011

digraph nfa { rankdir=LR;

world [shape = doublecircle]; hello [shape = circle]; goodbye [shape = circle];

hello -> world [label="greeting"]; goodbye -> world}

graph.dot

Page 36: RubyConf Argentina 2011

world

hellogreeting

goodbye

Page 37: RubyConf Argentina 2011

2 3.

4

/

/articles(.:format)

5

6 /articles/new(.:format)

0 1/ articles (?-mix:[^./?]+)

new

Page 38: RubyConf Argentina 2011

Journey

Page 39: RubyConf Argentina 2011

JourneyYes, it's named after the '70s rock sensation

Page 40: RubyConf Argentina 2011

What is a router?

Provides1: URL generation2: Path Recognition3: Route parsing

Page 41: RubyConf Argentina 2011

Why a new router?

Page 42: RubyConf Argentina 2011

Maintenance

Page 43: RubyConf Argentina 2011

0

750

1500

2250

3000

Journey Journey-2 Rack-Mount

LOC

Page 44: RubyConf Argentina 2011

Known algorithms

Page 45: RubyConf Argentina 2011

References

•Compilers: Principles, Techniques, & Tools (Aho, Lam, Sethi, Ullman)

• Intro to Formal Languages and Automata (Linz)

Page 46: RubyConf Argentina 2011

Predictability

Page 47: RubyConf Argentina 2011

CPU Time

Page 48: RubyConf Argentina 2011

Memory Usage

Page 49: RubyConf Argentina 2011

Current Performance

url generation path recognition route parsing

rack-mount Journey

Page 50: RubyConf Argentina 2011

me gusta

Page 51: RubyConf Argentina 2011

Patterns

Page 52: RubyConf Argentina 2011

Why patterns matter

Page 53: RubyConf Argentina 2011

Regular Expressions/om(g)!/

Page 54: RubyConf Argentina 2011

Rails Routes

Page 55: RubyConf Argentina 2011

resource :articles

Page 56: RubyConf Argentina 2011

/articles(.:format) /articles/new(.:format) /articles/:id/edit(.:format) /articles/:id(.:format)

Page 57: RubyConf Argentina 2011

Parens don't capture

Page 58: RubyConf Argentina 2011

:whatever => /([^./?]+)/

Page 59: RubyConf Argentina 2011

/articles(.:format)

/\/articles(?:\.([^.\/?]+))?$/

Page 60: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

Page 61: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

GET /articles/new

Page 62: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

GET /articles/new

Page 63: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

GET /articles/new

200 OK!

Page 64: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

Page 65: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

GET /foos/new

Page 66: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

GET /foos/new

Page 67: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

GET /foos/new

Page 68: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

GET /foos/new

Page 69: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

GET /foos/new

Page 70: RubyConf Argentina 2011

/\/articles(?:.([^.\/?]+))?$/

/\/articles\/new(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)\/edit(?:.([^.\/?]+))?$/

/\/articles\/([^.\/?]+)(?:.([^.\/?]+))?$/

GET /foos/new

404 Not Found

Page 71: RubyConf Argentina 2011

How long does this take?

Page 72: RubyConf Argentina 2011

r = routes.length

Page 73: RubyConf Argentina 2011

x = regexp compare

Page 74: RubyConf Argentina 2011

O(r ⨉ x)

Page 75: RubyConf Argentina 2011

Can we do better?

Page 76: RubyConf Argentina 2011

Finite State Machines

Parse Trees

Automata

Page 77: RubyConf Argentina 2011

Parse Trees

Page 78: RubyConf Argentina 2011

Parsing regexp

Page 79: RubyConf Argentina 2011

(a|b)*abb

Page 80: RubyConf Argentina 2011

○○ b

○ b

a *

a b

()

|

Describe node types

Page 81: RubyConf Argentina 2011

Parsing rails routes

Page 82: RubyConf Argentina 2011

Journey::Parserparser = Journey::Parser.newast = parser.parse '/articles(.:format)'

puts ast.to_dot

Page 83: RubyConf Argentina 2011

○ ()

/ articles ○

. :format

Page 84: RubyConf Argentina 2011

To String!

parser = Journey::Parser.newast = parser.parse '/articles(.:format)'puts ast.to_sputs ast.to_regexp

Page 85: RubyConf Argentina 2011

OR ASTparser = Journey::Parser.new

trees = [ '/articles(.:format)', '/articles/new(.:format)',].map { |s| parser.parse s }

ast = Journey::Nodes::Or.new trees

puts ast.to_dot

Page 86: RubyConf Argentina 2011

|

○ ○

○ ()

/ articles ○

. :format

○ ()

○ new

○ /

/ articles

. :format

Page 87: RubyConf Argentina 2011

SECRET FEATUREparser = Journey::Parser.newast = parser.parse '/articles|books(.:format)'

Page 88: RubyConf Argentina 2011

SECRET FEATUREparser = Journey::Parser.newast = parser.parse '/articles|books(.:format)'

SUPER SECRET!

Page 89: RubyConf Argentina 2011

Automata

Page 90: RubyConf Argentina 2011

(a|b)*abb

Page 91: RubyConf Argentina 2011

3

0b2a

b

1aa

b

b

a

Double circle is acceptance state

Page 92: RubyConf Argentina 2011

baabb

Page 93: RubyConf Argentina 2011

3

0b2a

b

1aa

b

b

a

Page 94: RubyConf Argentina 2011

3

0b2a

b

1aa

b

b

a

b

Page 95: RubyConf Argentina 2011

3

0b2a

b

1aa

b

b

a

ba

Page 96: RubyConf Argentina 2011

3

0b2a

b

1aa

b

b

a

baa

Page 97: RubyConf Argentina 2011

3

0b2a

b

1aa

b

b

a

baabb

Page 98: RubyConf Argentina 2011

aab

3

0b2a

b

1aa

b

b

a

Page 99: RubyConf Argentina 2011

Deterministic Finite Automaton

Page 100: RubyConf Argentina 2011

Only one path

Page 101: RubyConf Argentina 2011

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

Page 102: RubyConf Argentina 2011

FSM Simulation

Page 103: RubyConf Argentina 2011

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

Page 104: RubyConf Argentina 2011

class DFA ...

def move(from, symbol) @table[from][symbol] endend

move function

Page 105: RubyConf Argentina 2011

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

Page 106: RubyConf Argentina 2011

Time: O(n)n = string.length

Page 107: RubyConf Argentina 2011

me gusta

Page 108: RubyConf Argentina 2011

Space: S + Tstates.length + transitions.length

Page 109: RubyConf Argentina 2011

Nondeterministic Finite Automaton

Page 110: RubyConf Argentina 2011

Has nil edges

Page 111: RubyConf Argentina 2011

Can't tell direction

Page 112: RubyConf Argentina 2011

Simulation of NFA

Page 113: RubyConf Argentina 2011

602ε

3a

5b

εε

a|b

Page 114: RubyConf Argentina 2011

602ε

3a

5b

εε

nil-closure

Page 115: RubyConf Argentina 2011

602ε

3a ε

5b ε

a

Page 116: RubyConf Argentina 2011

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

Page 117: RubyConf Argentina 2011

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

Page 118: RubyConf Argentina 2011

Move function

class NFA ...

def move(states, symbol) states.map { |s| @table[s][symbol] }.flatten endend

Page 119: RubyConf Argentina 2011

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 }=> []

Page 120: RubyConf Argentina 2011

Time: O(r ⨉ x)r = operators.length, x = string.length

Page 121: RubyConf Argentina 2011

Who cares about NFA?

Page 122: RubyConf Argentina 2011

NFA Construction

Page 123: RubyConf Argentina 2011

○ ()

/ articles ○

. :format

/articles(.:format)

Page 124: RubyConf Argentina 2011

cat nodes

10 /

Page 125: RubyConf Argentina 2011

/articles

20 1/ articles

Page 126: RubyConf Argentina 2011

Optional

30ε

2????? ε

Page 127: RubyConf Argentina 2011

60 1/ 2articlesε

4. 5:format ε

Page 128: RubyConf Argentina 2011

parser = Journey::Parser.newast = parser.parse '/articles(.:format)'nfa = Journey::NFA::Builder.new ast

tt = nfa.transition_tableputs tt.to_dot

Journey::NFA

Page 129: RubyConf Argentina 2011

ConvertingNFA to DFA

Page 130: RubyConf Argentina 2011

Eliminate nil transitions

Page 131: RubyConf Argentina 2011

Collapse duplicate edges

Page 132: RubyConf Argentina 2011

60 1/ 2articlesε

4. 5:format ε

/articles(.:format)

Page 133: RubyConf Argentina 2011

2 3. 40 1/ articles :format

/articles(.:format)

Page 134: RubyConf Argentina 2011

CODES!

parser = Journey::Parser.newast = parser.parse '/articles(.:format)'nfa = Journey::NFA::Builder.new ast

tt = nfa.transition_table.generalized_tableputs tt.to_dot

Page 135: RubyConf Argentina 2011

SHORTER CODES!

parser = Journey::Parser.newast = parser.parse '/articles(.:format)'dfa = Journey::GTG::Builder.new ast

tt = dfa.transition_tableputs tt.to_dot

Page 136: RubyConf Argentina 2011

ANY NFAconverts to DFA

Page 137: RubyConf Argentina 2011

O(r ⨉ x) => O(x)r = operations.length, x = string.length

Page 138: RubyConf Argentina 2011

me gusta

Page 139: RubyConf Argentina 2011

Converting Automata to Regexp

Page 140: RubyConf Argentina 2011

2 3. 40 1/ articles :format

/articles(.:format)

Page 141: RubyConf Argentina 2011

2 3. 40 /articles :format

/articles(.:format)

Page 142: RubyConf Argentina 2011

/articles(.:format)

2 4.:format0 /articles

Page 143: RubyConf Argentina 2011

/articles(.:format)

40 /articles(.:format)?

Page 144: RubyConf Argentina 2011

Generalized Transition Graph

Page 145: RubyConf Argentina 2011

/users(.:format) /users/new(.:format) /users/:id/edit(.:format) /users/:id(.:format)

resource :users

Page 146: RubyConf Argentina 2011

2

3.

4/

5

6 8.

7 9/

10

.

11

12 14.

13

15

0 1/ users

(?-mix:[^./?]+)

new(?-mix:[^./?]+)

(?-mix:[^./?]+)

edit

(?-mix:[^./?]+)

(?-mix:[^./?]+)

resource :users

Page 147: RubyConf Argentina 2011

The Plan?

Page 148: RubyConf Argentina 2011

Combine All Routes

Page 149: RubyConf Argentina 2011

Produce DFA

Page 150: RubyConf Argentina 2011

Simulate in O(n) Time

Page 151: RubyConf Argentina 2011

Routing To The Future

Page 152: RubyConf Argentina 2011

JS Simulation

Page 153: RubyConf Argentina 2011

Table => JSON

parser = Journey::Parser.newast = parser.parse '/articles(.:format)'dfa = Journey::GTG::Builder.new ast

tt = dfa.transition_tableputs tt.to_json

Page 154: RubyConf Argentina 2011

Table => SVG

parser = Journey::Parser.newast = parser.parse '/articles(.:format)'dfa = Journey::GTG::Builder.new ast

tt = dfa.transition_tableputs tt.to_svg

Page 155: RubyConf Argentina 2011

JS Tokenizer

function tokenize(input, callback) { while(input.length > 0) { callback(input.match(/^[\/\.\?]|[^\/\.\?]+/)[0]); input = input.replace(/^[\/\.\?]|[^\/\.\?]+/, ''); }}

Page 156: RubyConf Argentina 2011

JS Simulator tokenize(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; });

Page 157: RubyConf Argentina 2011

d3.js

Page 158: RubyConf Argentina 2011
Page 159: RubyConf Argentina 2011

Rails Console

irb> File.open('out.html', 'wb') { |f|irb* f.write(irb* Wot::Application.routes.router.visualizerirb> )}=> 69074

Page 160: RubyConf Argentina 2011

routes.rb marshalling

Page 161: RubyConf Argentina 2011

Test suggestions

Page 162: RubyConf Argentina 2011

Test coverage

Page 163: RubyConf Argentina 2011

Usage Heat Maps

Page 164: RubyConf Argentina 2011

REGEXP

AST

NFA

DFA

Page 165: RubyConf Argentina 2011

ROFLSCALE!!!

Page 166: RubyConf Argentina 2011

DFA => YACC

Page 167: RubyConf Argentina 2011

DFA => RACC

Page 168: RubyConf Argentina 2011

DFA => Ragel

Page 169: RubyConf Argentina 2011

Open Questions

Page 170: RubyConf Argentina 2011

Is our GTG deterministic?

Page 171: RubyConf Argentina 2011

/users/new|/users/:id

4

5

0 1/ 2users 3/new

(?-mix:[^./?]+)

Page 172: RubyConf Argentina 2011

"new" =~ /new|[^.\/?]+/

Page 173: RubyConf Argentina 2011

Can we make it deterministic?

Page 174: RubyConf Argentina 2011

L1 = {new}L2 = {[^./?]+}

Page 175: RubyConf Argentina 2011

/users/new|/users/:id

4

5

0 1/ 2users 3/L1

L2 - L1

Page 176: RubyConf Argentina 2011

Is it worth our effort?

Page 177: RubyConf Argentina 2011

REGEXP

AST

NFA

DFA

Page 178: RubyConf Argentina 2011

Is it worth our effort?

Page 179: RubyConf Argentina 2011

Thank You!!

Page 180: RubyConf Argentina 2011

<3<3<3<3<3


Recommended