From 745d1a269b3fdc969abbb7181d534f41c2bcd5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Wed, 23 Aug 2023 15:58:26 +0200 Subject: [PATCH] MEDIUM: map/acl: Improve pat_ref_set_elt() efficiency (for "set-map", "add-acl"action perfs) Store a pointer to the expression (struct pattern_expr) into the data structure used to chain/store the map element references (struct pat_ref_elt) , e.g. the struct pattern_tree when stored into an ebtree or struct pattern_list when chained to a list. Modify pat_ref_set_elt() to stop inspecting all the expressions attached to a map and to look for the element passed as parameter to retrieve the sample data to be parsed. Indeed, thanks to the pointer added above to each pattern tree nodes or list elements, they all can be inspected directly from the passed as parameter and its ->tree_head and ->list_head member: the pattern tree nodes are stored into elt->tree_head, and the pattern list elements are chained to elt->list_head list. This inspection was also the job of pattern_find_smp() which is no more useful. This patch removes the code of this function. --- include/haproxy/pattern-t.h | 2 + src/pattern.c | 84 ++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/include/haproxy/pattern-t.h b/include/haproxy/pattern-t.h index 803620d78a..0947e8b7f5 100644 --- a/include/haproxy/pattern-t.h +++ b/include/haproxy/pattern-t.h @@ -138,6 +138,7 @@ struct pattern_tree { void *from_ref; // pattern_tree linked from pat_ref_elt, ends with NULL struct sample_data *data; struct pat_ref_elt *ref; + struct pattern_expr *expr; struct ebmb_node node; }; @@ -183,6 +184,7 @@ struct pattern_list { void *from_ref; // pattern_tree linked from pat_ref_elt, ends with NULL struct list list; struct pattern pat; + struct pattern_expr *expr; }; /* Description of a pattern expression. diff --git a/src/pattern.c b/src/pattern.c index c77d236088..231316ab6e 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -1204,6 +1204,7 @@ int pat_idx_list_val(struct pattern_expr *expr, struct pattern *pat, char **err) /* chain pattern in the expression */ LIST_APPEND(&expr->patterns, &patl->list); + patl->expr = expr; /* and from the reference */ patl->from_ref = pat->ref->list_head; pat->ref->list_head = &patl->from_ref; @@ -1237,6 +1238,7 @@ int pat_idx_list_ptr(struct pattern_expr *expr, struct pattern *pat, char **err) /* chain pattern in the expression */ LIST_APPEND(&expr->patterns, &patl->list); + patl->expr = expr; /* and from the reference */ patl->from_ref = pat->ref->list_head; pat->ref->list_head = &patl->from_ref; @@ -1271,6 +1273,7 @@ int pat_idx_list_str(struct pattern_expr *expr, struct pattern *pat, char **err) /* chain pattern in the expression */ LIST_APPEND(&expr->patterns, &patl->list); + patl->expr = expr; /* and from the reference */ patl->from_ref = pat->ref->list_head; pat->ref->list_head = &patl->from_ref; @@ -1305,6 +1308,7 @@ int pat_idx_list_reg_cap(struct pattern_expr *expr, struct pattern *pat, int cap /* chain pattern in the expression */ LIST_APPEND(&expr->patterns, &patl->list); + patl->expr = expr; /* and from the reference */ patl->from_ref = pat->ref->list_head; pat->ref->list_head = &patl->from_ref; @@ -1358,6 +1362,8 @@ int pat_idx_tree_ip(struct pattern_expr *expr, struct pattern *pat, char **err) /* Insert the entry. */ ebmb_insert_prefix(&expr->pattern_tree, &node->node, 4); + + node->expr = expr; node->from_ref = pat->ref->tree_head; pat->ref->tree_head = &node->from_ref; expr->ref->revision = rdtsc(); @@ -1389,6 +1395,8 @@ int pat_idx_tree_ip(struct pattern_expr *expr, struct pattern *pat, char **err) /* Insert the entry. */ ebmb_insert_prefix(&expr->pattern_tree_2, &node->node, 16); + + node->expr = expr; node->from_ref = pat->ref->tree_head; pat->ref->tree_head = &node->from_ref; expr->ref->revision = rdtsc(); @@ -1436,6 +1444,8 @@ int pat_idx_tree_str(struct pattern_expr *expr, struct pattern *pat, char **err) /* index the new node */ ebst_insert(&expr->pattern_tree, &node->node); + + node->expr = expr; node->from_ref = pat->ref->tree_head; pat->ref->tree_head = &node->from_ref; expr->ref->revision = rdtsc(); @@ -1481,6 +1491,8 @@ int pat_idx_tree_pfx(struct pattern_expr *expr, struct pattern *pat, char **err) /* index the new node */ ebmb_insert_prefix(&expr->pattern_tree, &node->node, len); + + node->expr = expr; node->from_ref = pat->ref->tree_head; pat->ref->tree_head = &node->from_ref; expr->ref->revision = rdtsc(); @@ -1697,6 +1709,10 @@ static inline int pat_ref_set_elt(struct pat_ref *ref, struct pat_ref_elt *elt, struct sample_data **data; char *sample; struct sample_data test; + struct pattern_tree *tree; + struct pattern_list *pat; + void **node; + /* Try all needed converters. */ list_for_each_entry(expr, &ref->pat, list) { @@ -1718,15 +1734,38 @@ static inline int pat_ref_set_elt(struct pat_ref *ref, struct pat_ref_elt *elt, /* Load sample in each reference. All the conversions are tested * below, normally these calls don't fail. */ - list_for_each_entry(expr, &ref->pat, list) { + for (node = elt->tree_head; node;) { + tree = container_of(node, struct pattern_tree, from_ref); + node = *node; + BUG_ON(tree->ref != elt); + expr = tree->expr; if (!expr->pat_head->parse_smp) continue; - HA_RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock); - data = pattern_find_smp(expr, elt); - if (data && *data && !expr->pat_head->parse_smp(sample, *data)) - *data = NULL; - HA_RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock); + data = &tree->data; + if (data && *data) { + HA_RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock); + if (!expr->pat_head->parse_smp(sample, *data)) + *data = NULL; + HA_RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock); + } + } + + for (node = elt->list_head; node;) { + pat = container_of(node, struct pattern_list, from_ref); + node = *node; + BUG_ON(pat->pat.ref != elt); + expr = pat->expr; + if (!expr->pat_head->parse_smp) + continue; + + data = &pat->pat.data; + if (data && *data) { + HA_RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock); + if (!expr->pat_head->parse_smp(sample, *data)) + *data = NULL; + HA_RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock); + } } /* free old sample only when all exprs are updated */ @@ -2581,39 +2620,6 @@ void pattern_prune(struct pattern_head *head) } } -/* This function searches occurrences of pattern reference element in - * expression and returns a pointer to a pointer of the sample storage. - * If is not found, NULL is returned. - */ -struct sample_data **pattern_find_smp(struct pattern_expr *expr, struct pat_ref_elt *ref) -{ - struct ebmb_node *node; - struct pattern_tree *elt; - struct pattern_list *pat; - - for (node = ebmb_first(&expr->pattern_tree); - node; - node = ebmb_next(node)) { - elt = container_of(node, struct pattern_tree, node); - if (elt->ref == ref) - return &elt->data; - } - - for (node = ebmb_first(&expr->pattern_tree_2); - node; - node = ebmb_next(node)) { - elt = container_of(node, struct pattern_tree, node); - if (elt->ref == ref) - return &elt->data; - } - - list_for_each_entry(pat, &expr->patterns, list) - if (pat->pat.ref == ref) - return &pat->pat.data; - - return NULL; -} - /* This function compares two pat_ref** on their unique_id, and returns -1/0/1 * depending on their order (suitable for sorting). */