From 8fb028149b69f383cf5aabe782ed1029f2fc0a6a Mon Sep 17 00:00:00 2001 From: Serdar Dogruyol Date: Sun, 16 Sep 2018 13:17:51 +0300 Subject: [PATCH 1/3] Cache http routes --- spec/spec_helper.cr | 1 + src/kemal/route_handler.cr | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 4d27003..0bc127a 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -83,5 +83,6 @@ end Spec.after_each do Kemal.config.clear Kemal::RouteHandler::INSTANCE.routes = Radix::Tree(Route).new + Kemal::RouteHandler::INSTANCE.cached_routes = Hash(String, Radix::Result(Route)).new Kemal::WebSocketHandler::INSTANCE.routes = Radix::Tree(WebSocket).new end diff --git a/src/kemal/route_handler.cr b/src/kemal/route_handler.cr index 95f9050..2e3ea3b 100644 --- a/src/kemal/route_handler.cr +++ b/src/kemal/route_handler.cr @@ -5,10 +5,11 @@ module Kemal include HTTP::Handler INSTANCE = new - property routes + property routes, cached_routes def initialize @routes = Radix::Tree(Route).new + @cached_routes = Hash(String, Radix::Result(Route)).new end def call(context : HTTP::Server::Context) @@ -22,9 +23,19 @@ module Kemal add_to_radix_tree("HEAD", path, Route.new("HEAD", path) { }) if method == "GET" end - # Check if a route is defined and returns the lookup + # Looks up the route from the Radix::Tree for the first time and caches to improve performance. def lookup_route(verb : String, path : String) - @routes.find radix_path(verb, path) + lookup_path = radix_path(verb, path) + + if cached_route = @cached_routes[lookup_path]? + return cached_route + end + + route = @routes.find(lookup_path) + + @cached_routes[lookup_path] = route if route.found? + + route end # Processes the route if it's a match. Otherwise renders 404. From 1a8a3c5b1d8b8d0a73b021d597b65d8cf09cde72 Mon Sep 17 00:00:00 2001 From: Serdar Dogruyol Date: Sun, 16 Sep 2018 15:34:43 +0300 Subject: [PATCH 2/3] Add cache size limit check to caching routes --- src/kemal/route_handler.cr | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/kemal/route_handler.cr b/src/kemal/route_handler.cr index 2e3ea3b..233289e 100644 --- a/src/kemal/route_handler.cr +++ b/src/kemal/route_handler.cr @@ -4,7 +4,8 @@ module Kemal class RouteHandler include HTTP::Handler - INSTANCE = new + INSTANCE = new + CACHED_ROUTES_LIMIT = 1024 property routes, cached_routes def initialize @@ -33,7 +34,11 @@ module Kemal route = @routes.find(lookup_path) - @cached_routes[lookup_path] = route if route.found? + if route.found? && @cached_routes.size < CACHED_ROUTES_LIMIT + @cached_routes[lookup_path] = route + else + @cached_routes.clear + end route end From 4bb56d23768ce57a25b304d054e051bcc8df4c9a Mon Sep 17 00:00:00 2001 From: Serdar Dogruyol Date: Mon, 17 Sep 2018 09:51:56 +0300 Subject: [PATCH 3/3] Only clear cached_routes if there's a route --- src/kemal/route_handler.cr | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/kemal/route_handler.cr b/src/kemal/route_handler.cr index 233289e..b0476c6 100644 --- a/src/kemal/route_handler.cr +++ b/src/kemal/route_handler.cr @@ -34,10 +34,9 @@ module Kemal route = @routes.find(lookup_path) - if route.found? && @cached_routes.size < CACHED_ROUTES_LIMIT + if route.found? + @cached_routes.clear if @cached_routes.size == CACHED_ROUTES_LIMIT @cached_routes[lookup_path] = route - else - @cached_routes.clear end route