Skip to content

Commit

Permalink
perf: add rax_tree_up() to iterate the routes tree (#136)
Browse files Browse the repository at this point in the history
  • Loading branch information
haoyang1994 authored Jan 17, 2024
1 parent ee3e37b commit 8ebc675
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 2 deletions.
20 changes: 19 additions & 1 deletion benchmark/match-prefix.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ for i = 1, route_count do
end

local rx = radix.new(routes)

ngx.say("case 1: route matched ")
ngx.update_time()
local start_time = ngx.now()

Expand All @@ -25,3 +25,21 @@ ngx.say("route count: ", route_count)
ngx.say("match times: ", match_times)
ngx.say("time used : ", used_time, " sec")
ngx.say("QPS : ", math.floor(match_times / used_time))

ngx.say("=================")
ngx.say("case 2: route not matched ")
ngx.update_time()
start_time = ngx.now()

path = "/" .. ngx.md5(route_count + 1) .. "/a"
for _ = 1, match_times do
res = rx:match(path)
end

ngx.update_time()
local used_time = ngx.now() - start_time
ngx.say("matched res: ", res)
ngx.say("route count: ", route_count)
ngx.say("match times: ", match_times)
ngx.say("time used : ", used_time, " sec")
ngx.say("QPS : ", math.floor(match_times / used_time))
3 changes: 2 additions & 1 deletion lib/resty/radixtree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ ffi_cdef[[
void *radix_tree_search(void *t, void *it, const unsigned char *buf,
size_t len);
int radix_tree_prev(void *it, const unsigned char *buf, size_t len);
int radix_tree_up(void *it, const unsigned char *buf, size_t len);
int radix_tree_stop(void *it);
void *radix_tree_new_it(void *t);
Expand Down Expand Up @@ -847,7 +848,7 @@ local function match_route(self, path, opts, args)
end

while true do
local idx = radix.radix_tree_prev(it, path, #path)
local idx = radix.radix_tree_up(it, path, #path)
if idx <= 0 then
break
end
Expand Down
24 changes: 24 additions & 0 deletions src/easy_rax.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,30 @@ radix_tree_prev(void *it, const unsigned char *buf, size_t len)
}


int
radix_tree_up(void *it, const unsigned char *buf, size_t len)
{
raxIterator *iter = it;
int res;

while (1) {
res = raxUp(iter);
if (!res) {
return -1;
}

if (iter->key_len > len ||
memcmp(buf, iter->key, iter->key_len) != 0) {
continue;
}

break;
}

return (int)iter->data;
}


int
radix_tree_stop(void *it)
{
Expand Down
1 change: 1 addition & 0 deletions src/easy_rax.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ void *radix_tree_find(void *t, const unsigned char *buf, size_t len);
void *radix_tree_search(void *t, void *it, const unsigned char *buf, size_t len);
int radix_tree_prev(void *it, const unsigned char *buf, size_t len);
int radix_tree_next(void *it, const unsigned char *buf, size_t len);
int radix_tree_up(void *it, const unsigned char *buf, size_t len);
int radix_tree_stop(void *it);

void *radix_tree_new_it(void *t);
Expand Down
54 changes: 54 additions & 0 deletions src/rax.c
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,48 @@ int raxIteratorPrevStep(raxIterator *it, int noup) {
}
}


int raxIteratorUpStep(raxIterator *it) {
if (it->flags & RAX_ITER_EOF) {
return 1;
} else if (it->flags & RAX_ITER_JUST_SEEKED) {
it->flags &= ~RAX_ITER_JUST_SEEKED;
return 1;
}

/* Save key len, stack items and the node where we are currently
* so that on iterator EOF we can restore the current key and state. */
size_t orig_key_len = it->key_len;
size_t orig_stack_items = it->stack.items;
raxNode *orig_node = it->node;

while(1) {
/* Already on head? Can't go up, iteration finished. */
if (it->node == it->rt->head) {
it->flags |= RAX_ITER_EOF;
it->stack.items = orig_stack_items;
it->key_len = orig_key_len;
it->node = orig_node;
return 1;
}

it->node = raxStackPop(&it->stack);

/* Adjust the current key to represent the node we are
* at. */
int todel = it->node->iscompr ? it->node->size : 1;
raxIteratorDelChars(it,todel);

/* Return the key: this could be the key we found scanning a new
* subtree, or if we did not find a new subtree to explore here,
* before giving up with this node, check if it's a key itself. */
if (it->node->iskey) {
it->data = raxGetData(it->node);
return 1;
}
}
}

/* Seek an iterator at the specified element.
* Return 0 if the seek failed for syntax error or out of memory. Otherwise
* 1 is returned. When 0 is returned for out of memory, errno is set to
Expand Down Expand Up @@ -1718,6 +1760,18 @@ int raxPrev(raxIterator *it) {
return 1;
}

int raxUp(raxIterator *it) {
if (!raxIteratorUpStep(it)) {
errno = ENOMEM;
return 0;
}
if (it->flags & RAX_ITER_EOF) {
errno = 0;
return 0;
}
return 1;
}

/* Compare the key currently pointed by the iterator to the specified
* key according to the specified operator. Returns 1 if the comparison is
* true, otherwise 0 is returned. */
Expand Down
1 change: 1 addition & 0 deletions src/rax.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ void raxStart(raxIterator *it, rax *rt);
int raxSeek(raxIterator *it, const char *op, unsigned char *ele, size_t len);
int raxNext(raxIterator *it);
int raxPrev(raxIterator *it);
int raxUp(raxIterator *it);
int raxCompare(raxIterator *iter, const char *op, unsigned char *key, size_t key_len);
void raxStop(raxIterator *it);
int raxEOF(raxIterator *it);
Expand Down

0 comments on commit 8ebc675

Please sign in to comment.