Skip to content

Commit f77aee9

Browse files
authored
optimize: make host match 20x faster (#61)
1. avoid varg to make host match JIT-compiled 2. avoid calling lj_tab_len too many times
1 parent d293309 commit f77aee9

File tree

3 files changed

+78
-11
lines changed

3 files changed

+78
-11
lines changed

benchmark/match-hosts.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local radix = require("resty.radixtree")
22
local route_count = 1000 * 1
3-
local match_times = 1000 * 5
3+
local match_times = 1000 * 100
44

55
local path = "/12345"
66
local routes = {}

lib/resty/radixtree.lua

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ local lrucache = require("resty.lrucache")
2626
local bit = require("bit")
2727
local ngx = ngx
2828
local table = table
29+
local clear_tab = base.clear_tab
2930
local new_tab = base.new_tab
3031
local tonumber = tonumber
3132
local ipairs = ipairs
@@ -39,7 +40,9 @@ local io = io
3940
local package = package
4041
local getmetatable=getmetatable
4142
local setmetatable=setmetatable
43+
local select = select
4244
local type = type
45+
local unpack = unpack
4346
local error = error
4447
local newproxy = newproxy
4548
local cur_level = ngx.config.subsystem == "http" and
@@ -536,7 +539,7 @@ local function compare_val(l_v, op, r_v, opts)
536539
end
537540

538541

539-
local function match_route_opts(route, opts, ...)
542+
local function match_route_opts(route, opts, args)
540543
local method = opts.method
541544
local opts_matched_exists = (opts.matched ~= nil)
542545
if route.method ~= 0 then
@@ -569,7 +572,8 @@ local function match_route_opts(route, opts, ...)
569572
local hosts = route.hosts
570573
local host = opts.host
571574
if host then
572-
for i = 1, #hosts, 2 do
575+
local len = #hosts
576+
for i = 1, len, 2 do
573577
if match_host(hosts[i], hosts[i + 1], host) then
574578
if opts_matched_exists then
575579
if hosts[i] then
@@ -607,7 +611,18 @@ local function match_route_opts(route, opts, ...)
607611
end
608612

609613
if route.filter_fun then
610-
if not route.filter_fun(opts.vars or ngx_var, opts, ...) then
614+
local fn = route.filter_fun
615+
local ok
616+
if args then
617+
-- now we can safely clear the self.args
618+
local args_len = args[0]
619+
args[0] = nil
620+
ok = fn(opts.vars or ngx_var, opts, unpack(args, 1, args_len))
621+
else
622+
ok = fn(opts.vars or ngx_var, opts)
623+
end
624+
625+
if not ok then
611626
return false
612627
end
613628
end
@@ -616,7 +631,7 @@ local function match_route_opts(route, opts, ...)
616631
end
617632

618633

619-
local function _match_from_routes(routes, path, opts, ...)
634+
local function _match_from_routes(routes, path, opts, args)
620635
if opts == empty_table then
621636
local route = routes[1]
622637
if not route or route.method == 0 then
@@ -628,7 +643,7 @@ local function _match_from_routes(routes, path, opts, ...)
628643
for _, route in ipairs(routes) do
629644
if route.path_op == "=" then
630645
if route.path == path then
631-
if match_route_opts(route, opts, ...) then
646+
if match_route_opts(route, opts, args) then
632647
if opts_matched_exists then
633648
opts.matched._path = path
634649
end
@@ -638,7 +653,7 @@ local function _match_from_routes(routes, path, opts, ...)
638653
goto continue
639654
end
640655

641-
if match_route_opts(route, opts, ...) then
656+
if match_route_opts(route, opts, args) then
642657
-- log_info("matched route: ", require("cjson").encode(route))
643658
-- log_info("matched path: ", path)
644659
if compare_param(path, route, opts) then
@@ -656,7 +671,7 @@ local function _match_from_routes(routes, path, opts, ...)
656671
end
657672

658673

659-
local function match_route(self, path, opts, ...)
674+
local function match_route(self, path, opts, args)
660675
if opts.matched then
661676
clear_tab(opts.matched)
662677
end
@@ -665,7 +680,7 @@ local function match_route(self, path, opts, ...)
665680
if routes then
666681
local opts_matched_exists = (opts.matched ~= nil)
667682
for _, route in ipairs(routes) do
668-
if match_route_opts(route, opts, ...) then
683+
if match_route_opts(route, opts, args) then
669684
if opts_matched_exists then
670685
opts.matched._path = path
671686
end
@@ -687,7 +702,7 @@ local function match_route(self, path, opts, ...)
687702

688703
routes = self.match_data[idx]
689704
if routes then
690-
local route = _match_from_routes(routes, path, opts, ...)
705+
local route = _match_from_routes(routes, path, opts, args)
691706
if route then
692707
return route
693708
end
@@ -715,7 +730,25 @@ function _M.dispatch(self, path, opts, ...)
715730
error("invalid argument path", 2)
716731
end
717732

718-
local route, err = match_route(self, path, opts or empty_table, ...)
733+
local args
734+
local len = select('#', ...)
735+
if len > 0 then
736+
if not self.args then
737+
self.args = {...}
738+
else
739+
clear_tab(self.args)
740+
for i = 1, len do
741+
self.args[i] = select(i, ...)
742+
end
743+
end
744+
745+
-- To keep the self.args in safe,
746+
-- we can't yield until filter_fun is called
747+
args = self.args
748+
args[0] = len
749+
end
750+
751+
local route, err = match_route(self, path, opts or empty_table, args)
719752
if not route then
720753
if err then
721754
return nil, err

t/filter-fun.t

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,37 @@ handler /aa
140140
true
141141
handler /aa
142142
true
143+
144+
145+
146+
=== TEST 5: dispatch(path, opt, ...) with nil arg
147+
--- config
148+
location /t {
149+
content_by_lua_block {
150+
local opts = {vars = ngx.var}
151+
local radix = require("resty.radixtree")
152+
local rx = radix.new({
153+
{
154+
paths = "/aa",
155+
filter_fun = function(vars, opt, a, b, c)
156+
ngx.log(ngx.WARN, "get arguments: ", a, ",", b, ",", c)
157+
return true
158+
end,
159+
handler = function (...)
160+
ngx.say("handler /aa")
161+
end,
162+
}
163+
})
164+
165+
ngx.say(rx:dispatch("/aa", opts, 1, nil, 3))
166+
}
167+
}
168+
--- request
169+
GET /t
170+
--- no_error_log
171+
[error]
172+
--- error_log
173+
get arguments: 1,nil,3
174+
--- response_body
175+
handler /aa
176+
true

0 commit comments

Comments
 (0)