From: Josef 'Jeff' Sipek Date: Fri, 30 Apr 2021 16:41:55 +0000 (-0400) Subject: lib: event filter - Avoid using event name wildcard matching when not needed X-Git-Tag: 2.3.16~165 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=33e01c1c3023726cf34d262d08810b6f0150c41f;p=thirdparty%2Fdovecot%2Fcore.git lib: event filter - Avoid using event name wildcard matching when not needed 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. --- diff --git a/src/lib/event-filter-parser.y b/src/lib/event-filter-parser.y index 03477763a8..640b48bc05 100644 --- a/src/lib/event-filter-parser.y +++ b/src/lib/event-filter-parser.y @@ -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; diff --git a/src/lib/event-filter-private.h b/src/lib/event-filter-private.h index 632ae46ca7..e5f05ea0a1 100644 --- a/src/lib/event-filter-private.h +++ b/src/lib/event-filter-private.h @@ -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 */ diff --git a/src/lib/event-filter.c b/src/lib/event-filter.c index 315aa0f397..49f3d3e908 100644 --- a/src/lib/event-filter.c +++ b/src/lib/event-filter.c @@ -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: