Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove paths part size hash from Matcher #28

Merged
merged 3 commits into from
Jul 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/benchmark.cr
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ router.add("get", "/users/:id/edit", :edit)
router.add("get", "/users/:id/new", :new)

elapsed_times = [] of Time::Span
1000.times do
10.times do
elapsed = Time.measure do
1000.times do
100_000.times do
router.match!("post", "/users")
router.match!("get", "/users/1")
router.match!("delete", "/users/1")
Expand Down
26 changes: 9 additions & 17 deletions src/lucky_router/matcher.cr
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,7 @@ class LuckyRouter::Matcher(T)
alias RoutePartsSize = Int32
alias HttpMethod = String

# The matcher stores routes based on the HTTP method and the number of
# "parts" in the path
#
# Each section in between the path is a "part". We use the method and part size
# to both speed up the route lookup and makes it more reliable because the router
# always tries to find routes that are the right size.
# The matcher stores routes based on the HTTP method
#
# Each route key is a `Fragment(T)`. Where `T` is the type of the payload. See
# `Fragment` for details on how it works
Expand All @@ -40,15 +35,13 @@ class LuckyRouter::Matcher(T)
# # Will make @routes look like:

# {
# "get" => {
# 2 => Fragment(T) # The fragment for this route
# }
# "get" => Fragment(T) # The fragment for this route
# }
# ```
#
# So if trying to match "/users/1/foo" it will not even try because the parts
# size does not match any of the known routes.
@routes = Hash(HttpMethod, Hash(RoutePartsSize, Fragment(T))).new
# So if trying to match a POST request it will not even try because the request
# method does not match any of the known routes.
@routes = Hash(HttpMethod, Fragment(T)).new

def add(method : String, path : String, payload : T)
all_path_parts = path.split("/")
Expand Down Expand Up @@ -79,8 +72,8 @@ class LuckyRouter::Matcher(T)

def match(method : String, path_to_match : String) : Match(T)?
parts_to_match = extract_parts(path_to_match)
return if routes[method]?.try(&.[parts_to_match.size]?).nil?
match = routes[method][parts_to_match.size].find(parts_to_match)
return unless routes[method]?
match = routes[method].find(parts_to_match)

if match.is_a?(Match)
match
Expand All @@ -98,8 +91,7 @@ class LuckyRouter::Matcher(T)
end

private def add_route(method : String, parts : Array(String), payload : T)
routes[method] ||= Hash(RoutePartsSize, Fragment(T)).new
routes[method][parts.size] ||= Fragment(T).new
routes[method][parts.size].process_parts(parts, payload)
routes[method] ||= Fragment(T).new
routes[method].process_parts(parts, payload)
end
end