perf(topicidx): implement fast-forwarding prefixes

This should give less `ets:next/2` calls in general and much less
when index has relatively small number of long non-wildcard topics.
This commit is contained in:
Andrew Mayorov 2023-08-04 19:27:43 +04:00
parent 0c7bdbdab4
commit fd0986071c
No known key found for this signature in database
GPG Key ID: 2837C62ACFBFED5D
2 changed files with 26 additions and 4 deletions

View File

@ -73,7 +73,13 @@ match(K, Prefix, Words, RPrefix, Tab) ->
match_rest(Matched, Words, RPrefix, Tab)
end.
match_rest(false, [W | Rest], RPrefix, Tab) ->
match_rest([W1 | [W2 | _] = SLast], [W1 | [W2 | _] = Rest], RPrefix, Tab) ->
% NOTE
% Fast-forward through identical words in the topic and the last key suffixes.
% This should save us a few redundant `ets:next` calls at the cost of slightly
% more complex match patterns.
match_rest(SLast, Rest, [W1 | RPrefix], Tab);
match_rest(SLast, [W | Rest], RPrefix, Tab) when is_list(SLast) ->
match(Rest, [W | RPrefix], Tab);
match_rest(plus, [W | Rest], RPrefix, Tab) ->
case match(Rest, ['+' | RPrefix], Tab) of
@ -115,7 +121,13 @@ matches(K, Prefix, Words, RPrefix, Acc, Tab) ->
matches_rest(Matched, Words, RPrefix, Acc, Tab)
end.
matches_rest(false, [W | Rest], RPrefix, Acc, Tab) ->
matches_rest([W1 | [W2 | _] = SLast], [W1 | [W2 | _] = Rest], RPrefix, Acc, Tab) ->
% NOTE
% Fast-forward through identical words in the topic and the last key suffixes.
% This should save us a few redundant `ets:next` calls at the cost of slightly
% more complex match patterns.
matches_rest(SLast, Rest, [W1 | RPrefix], Acc, Tab);
matches_rest(SLast, [W | Rest], RPrefix, Acc, Tab) when is_list(SLast) ->
matches(Rest, [W | RPrefix], Acc, Tab);
matches_rest(plus, [W | Rest], RPrefix, Acc, Tab) ->
NAcc = matches(Rest, ['+' | RPrefix], Acc, Tab),
@ -143,8 +155,8 @@ match_filter([], ['#'], _Suffix) ->
true;
match_filter([], ['+' | _], _Suffix) ->
plus;
match_filter([], [_H | _], _Suffix) ->
false;
match_filter([], [_H | _] = Rest, _Suffix) ->
Rest;
match_filter([H | T1], [H | T2], Suffix) ->
match_filter(T1, T2, Suffix);
match_filter([H1 | _], [H2 | _], _Suffix) when H2 > H1 ->

View File

@ -133,6 +133,16 @@ t_match7(_) ->
emqx_topic_index:insert(W, t_match7, <<>>, Tab),
?assertEqual(W, topic(match(T, Tab))).
t_match_fast_forward(_) ->
Tab = emqx_topic_index:new(),
emqx_topic_index:insert(<<"a/b/1/2/3/4/5/6/7/8/9/#">>, id1, <<>>, Tab),
emqx_topic_index:insert(<<"z/y/x/+/+">>, id2, <<>>, Tab),
emqx_topic_index:insert(<<"a/b/c/+">>, id3, <<>>, Tab),
% dbg:tracer(),
% dbg:p(all, c),
% dbg:tpl({ets, next, '_'}, x),
?assertEqual([id1], [id(M) || M <- matches(<<"a/b/1/2/3/4/5/6/7/8/9/0">>, Tab)]).
t_match_unique(_) ->
Tab = emqx_topic_index:new(),
emqx_topic_index:insert(<<"a/b/c">>, t_match_id1, <<>>, Tab),