]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: event filter - Avoid using event name wildcard matching when not needed
authorJosef 'Jeff' Sipek <jeff.sipek@open-xchange.com>
Fri, 30 Apr 2021 16:41:55 +0000 (12:41 -0400)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Mon, 10 May 2021 11:42:42 +0000 (11:42 +0000)
If the right hand side of an event name comparison is not using any
wildcards, we can compare using strcmp() instead of the more expensive
wildcard_match().

This wildcard matching avoidance change speeds up matching quite a bit.
When the desired comparison is *not* a wildcard match (i.e., the filter is
'event=abc'), microbenchmarks show at least a 30% speedup in filter matching
speed.  When the comparison includes a wildcard (i.e., the filter is
'event=abc*'), microbenchmarks show approximately 0.4% filer matching
slowdown.

Since there are so many non-wildcard matches in a typical filter, this is a
very good trade-off.

src/lib/event-filter-parser.y
src/lib/event-filter-private.h
src/lib/event-filter.c

index 03477763a84185532834baf3c0f36738af0edc30..640b48bc0587e289bacdfce2bbc67dff5c929c3a 100644 (file)
@@ -10,6 +10,7 @@
 
 %{
 #include "lib.h"
+#include "wildcard-match.h"
 #include "lib-event-private.h"
 #include "event-filter-private.h"
 
@@ -58,6 +59,8 @@ static struct event_filter_node *key_value(struct event_filter_parser_state *sta
                i_unreached();
        case EVENT_FILTER_NODE_TYPE_EVENT_NAME_WILDCARD:
                node->str = p_strdup(state->pool, b);
+               if (wildcard_is_literal(node->str))
+                       node->type = EVENT_FILTER_NODE_TYPE_EVENT_NAME_EXACT;
                state->has_event_name = TRUE;
                break;
        case EVENT_FILTER_NODE_TYPE_EVENT_SOURCE_LOCATION: {
@@ -100,6 +103,8 @@ static struct event_filter_node *key_value(struct event_filter_parser_state *sta
                        node->field.value.intmax = INT_MIN;
                }
                break;
+       case EVENT_FILTER_NODE_TYPE_EVENT_NAME_EXACT:
+               i_unreached();
        }
 
        return node;
index 632ae46ca74f443adc60fffd37521c4508ca7a49..e5f05ea0a1c9d51ef6f0421cb9e3f1cc745c8ae8 100644 (file)
@@ -20,6 +20,7 @@ enum event_filter_node_type {
        EVENT_FILTER_NODE_TYPE_LOGIC = 1, /* children */
 
        /* leaf nodes */
+       EVENT_FILTER_NODE_TYPE_EVENT_NAME_EXACT, /* str */
        EVENT_FILTER_NODE_TYPE_EVENT_NAME_WILDCARD, /* str */
        EVENT_FILTER_NODE_TYPE_EVENT_SOURCE_LOCATION, /* str + int */
        EVENT_FILTER_NODE_TYPE_EVENT_CATEGORY, /* cat */
index 315aa0f397ba7c0d3710744cefa03aca66e18466..49f3d3e908a433380d5109ea90b2663e7d67d5f0 100644 (file)
@@ -290,6 +290,8 @@ void event_filter_add(struct event_filter *filter,
                node->type = EVENT_FILTER_NODE_TYPE_EVENT_NAME_WILDCARD;
                node->op = EVENT_FILTER_OP_CMP_EQ;
                node->str = p_strdup(filter->pool, query->name);
+               if (wildcard_is_literal(query->name))
+                       node->type = EVENT_FILTER_NODE_TYPE_EVENT_NAME_EXACT;
 
                add_node(filter->pool, &expr, node, EVENT_FILTER_OP_AND);
        }
@@ -435,6 +437,7 @@ event_filter_export_query_expr(const struct event_filter_query_internal *query,
                }
                str_append_c(dest, ')');
                break;
+       case EVENT_FILTER_NODE_TYPE_EVENT_NAME_EXACT:
        case EVENT_FILTER_NODE_TYPE_EVENT_NAME_WILDCARD:
                str_append(dest, "event");
                str_append(dest, event_filter_export_query_expr_op(node->op));
@@ -631,6 +634,9 @@ event_filter_query_match_cmp(struct event_filter_node *node,
        switch (node->type) {
                case EVENT_FILTER_NODE_TYPE_LOGIC:
                        i_unreached();
+               case EVENT_FILTER_NODE_TYPE_EVENT_NAME_EXACT:
+                       return (event->sending_name != NULL) &&
+                              strcmp(event->sending_name, node->str) == 0;
                case EVENT_FILTER_NODE_TYPE_EVENT_NAME_WILDCARD:
                        return (event->sending_name != NULL) &&
                               wildcard_match(event->sending_name, node->str);
@@ -806,6 +812,7 @@ event_filter_query_update_category(struct event_filter_query_internal *query,
                event_filter_query_update_category(query, node->children[0], category, add);
                event_filter_query_update_category(query, node->children[1], category, add);
                break;
+       case EVENT_FILTER_NODE_TYPE_EVENT_NAME_EXACT:
        case EVENT_FILTER_NODE_TYPE_EVENT_NAME_WILDCARD:
        case EVENT_FILTER_NODE_TYPE_EVENT_SOURCE_LOCATION:
        case EVENT_FILTER_NODE_TYPE_EVENT_FIELD: