Skip to content

Commit 69bfc52

Browse files
committed
Flatten the transition table state arrays
Using arrays of arrays means lots of extra small allocations we can instead store it all in a single array.
1 parent d3e1fb4 commit 69bfc52

File tree

3 files changed

+15
-14
lines changed

3 files changed

+15
-14
lines changed

actionpack/lib/action_dispatch/journey/gtg/simulator.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Simulator # :nodoc:
2020
STATIC_TOKENS["?".ord] = "?"
2121
STATIC_TOKENS.freeze
2222

23-
INITIAL_STATE = [ [0, nil] ].freeze
23+
INITIAL_STATE = [0, nil].freeze
2424

2525
attr_reader :tt
2626

@@ -50,9 +50,9 @@ def memos(string)
5050
end
5151
end
5252

53-
acceptance_states = state.each_with_object([]) do |s_d, memos|
54-
s, idx = s_d
55-
memos.concat(tt.memo(s)) if idx.nil? && tt.accepting?(s)
53+
acceptance_states = []
54+
state.each_slice(2) do |s, idx|
55+
acceptance_states.concat(tt.memo(s)) if idx.nil? && tt.accepting?(s)
5656
end
5757

5858
acceptance_states.empty? ? yield : acceptance_states

actionpack/lib/action_dispatch/journey/gtg/transition_table.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,18 @@ def move(t, full_string, token, start_index, token_matches_default)
5252

5353
next_states = []
5454

55-
t.each { |s, previous_start|
55+
t.each_slice(2) { |s, previous_start|
5656
if previous_start.nil?
5757
# In the simple case of a "default" param regex do this fast-path and add all
5858
# next states.
5959
if token_matches_default && std_state = @stdparam_states[s]
60-
next_states << [std_state, nil].freeze
60+
next_states << std_state << nil
6161
end
6262

6363
# When we have a literal string, we can just pull the next state
6464
if states = @string_states[s]
65-
next_states << [states[token], nil].freeze unless states[token].nil?
65+
state = states[token]
66+
next_states << state << nil unless state.nil?
6667
end
6768
end
6869

@@ -82,12 +83,12 @@ def move(t, full_string, token, start_index, token_matches_default)
8283

8384
states.each { |re, v|
8485
# if we match, we can try moving past this
85-
next_states << [v, nil].freeze if !v.nil? && re.match?(curr_slice)
86+
next_states << v << nil if !v.nil? && re.match?(curr_slice)
8687
}
8788

8889
# and regardless, we must continue accepting tokens and retrying this regexp. we
8990
# need to remember where we started as well so we can take bigger slices.
90-
next_states << [s, slice_start].freeze
91+
next_states << s << slice_start
9192
end
9293
}
9394

actionpack/test/journey/gtg/builder_test.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ module GTG
88
class TestBuilder < ActiveSupport::TestCase
99
def test_following_states_multi
1010
table = tt ["a|a"]
11-
assert_equal 1, table.move([[0, nil]], "a", "a", 0, true).length
11+
assert_equal 1, table.move([0, nil], "a", "a", 0, true).each_slice(2).count
1212
end
1313

1414
def test_following_states_multi_regexp
1515
table = tt [":a|b"]
16-
assert_equal 1, table.move([[0, nil]], "fooo", "fooo", 0, true).length
17-
assert_equal 2, table.move([[0, nil]], "b", "b", 0, true).length
16+
assert_equal 1, table.move([0, nil], "fooo", "fooo", 0, true).each_slice(2).count
17+
assert_equal 2, table.move([0, nil], "b", "b", 0, true).each_slice(2).count
1818
end
1919

2020
def test_multi_path
@@ -25,9 +25,9 @@ def test_multi_path
2525
[2, "b"],
2626
[2, "/"],
2727
[1, "c"],
28-
].inject([[0, nil]]) { |state, (exp, sym)|
28+
].inject([0, nil]) { |state, (exp, sym)|
2929
new = table.move(state, sym, sym, 0, sym != "/")
30-
assert_equal exp, new.length
30+
assert_equal exp, new.each_slice(2).count
3131
new
3232
}
3333
end

0 commit comments

Comments
 (0)