Blame SOURCES/0005-intervals-Do-not-sort-cached-set-elements-over-and-o.patch

ddb7af
From 013a3b226a0fa5f7a8469bae736150cbf2d092c4 Mon Sep 17 00:00:00 2001
ddb7af
From: Phil Sutter <psutter@redhat.com>
ddb7af
Date: Fri, 24 Jun 2022 16:02:59 +0200
ddb7af
Subject: [PATCH] intervals: Do not sort cached set elements over and over
ddb7af
 again
ddb7af
ddb7af
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1917398
ddb7af
Upstream Status: nftables commit 59e3a59221fb8
ddb7af
ddb7af
commit 59e3a59221fb81c289a0868a85140dd452fb1c30
ddb7af
Author: Phil Sutter <phil@nwl.cc>
ddb7af
Date:   Thu Jun 16 10:56:12 2022 +0200
ddb7af
ddb7af
    intervals: Do not sort cached set elements over and over again
ddb7af
ddb7af
    When adding element(s) to a non-empty set, code merged the two lists and
ddb7af
    sorted the result. With many individual 'add element' commands this
ddb7af
    causes substantial overhead. Make use of the fact that
ddb7af
    existing_set->init is sorted already, sort only the list of new elements
ddb7af
    and use list_splice_sorted() to merge the two sorted lists.
ddb7af
ddb7af
    Add set_sort_splice() and use it for set element overlap detection and
ddb7af
    automerge.
ddb7af
ddb7af
    A test case adding ~25k elements in individual commands completes in
ddb7af
    about 1/4th of the time with this patch applied.
ddb7af
ddb7af
    Joint work with Pablo.
ddb7af
ddb7af
    Fixes: 3da9643fb9ff9 ("intervals: add support to automerge with kernel elements")
ddb7af
    Signed-off-by: Phil Sutter <phil@nwl.cc>
ddb7af
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
ddb7af
ddb7af
Signed-off-by: Phil Sutter <psutter@redhat.com>
ddb7af
---
ddb7af
 include/expression.h |  1 +
ddb7af
 src/intervals.c      | 46 +++++++++++++++++++++-----------------------
ddb7af
 src/mergesort.c      |  2 +-
ddb7af
 3 files changed, 24 insertions(+), 25 deletions(-)
ddb7af
ddb7af
diff --git a/include/expression.h b/include/expression.h
ddb7af
index 53194c9..cf7319b 100644
ddb7af
--- a/include/expression.h
ddb7af
+++ b/include/expression.h
ddb7af
@@ -481,6 +481,7 @@ extern struct expr *compound_expr_alloc(const struct location *loc,
ddb7af
 extern void compound_expr_add(struct expr *compound, struct expr *expr);
ddb7af
 extern void compound_expr_remove(struct expr *compound, struct expr *expr);
ddb7af
 extern void list_expr_sort(struct list_head *head);
ddb7af
+extern void list_splice_sorted(struct list_head *list, struct list_head *head);
ddb7af
 
ddb7af
 extern struct expr *concat_expr_alloc(const struct location *loc);
ddb7af
 
ddb7af
diff --git a/src/intervals.c b/src/intervals.c
ddb7af
index e203413..dcc06d1 100644
ddb7af
--- a/src/intervals.c
ddb7af
+++ b/src/intervals.c
ddb7af
@@ -118,6 +118,26 @@ static bool merge_ranges(struct set_automerge_ctx *ctx,
ddb7af
 	return false;
ddb7af
 }
ddb7af
 
ddb7af
+static void set_sort_splice(struct expr *init, struct set *set)
ddb7af
+{
ddb7af
+	struct set *existing_set = set->existing_set;
ddb7af
+
ddb7af
+	set_to_range(init);
ddb7af
+	list_expr_sort(&init->expressions);
ddb7af
+
ddb7af
+	if (!existing_set)
ddb7af
+		return;
ddb7af
+
ddb7af
+	if (existing_set->init) {
ddb7af
+		set_to_range(existing_set->init);
ddb7af
+		list_splice_sorted(&existing_set->init->expressions,
ddb7af
+				   &init->expressions);
ddb7af
+		init_list_head(&existing_set->init->expressions);
ddb7af
+	} else {
ddb7af
+		existing_set->init = set_expr_alloc(&internal_location, set);
ddb7af
+	}
ddb7af
+}
ddb7af
+
ddb7af
 static void setelem_automerge(struct set_automerge_ctx *ctx)
ddb7af
 {
ddb7af
 	struct expr *i, *next, *prev = NULL;
ddb7af
@@ -222,18 +242,7 @@ int set_automerge(struct list_head *msgs, struct cmd *cmd, struct set *set,
ddb7af
 		return 0;
ddb7af
 	}
ddb7af
 
ddb7af
-	if (existing_set) {
ddb7af
-		if (existing_set->init) {
ddb7af
-			list_splice_init(&existing_set->init->expressions,
ddb7af
-					 &init->expressions);
ddb7af
-		} else {
ddb7af
-			existing_set->init = set_expr_alloc(&internal_location,
ddb7af
-							    set);
ddb7af
-		}
ddb7af
-	}
ddb7af
-
ddb7af
-	set_to_range(init);
ddb7af
-	list_expr_sort(&init->expressions);
ddb7af
+	set_sort_splice(init, set);
ddb7af
 
ddb7af
 	ctx.purge = set_expr_alloc(&internal_location, set);
ddb7af
 
ddb7af
@@ -591,18 +600,7 @@ int set_overlap(struct list_head *msgs, struct set *set, struct expr *init)
ddb7af
 	struct expr *i, *n, *clone;
ddb7af
 	int err;
ddb7af
 
ddb7af
-	if (existing_set) {
ddb7af
-		if (existing_set->init) {
ddb7af
-			list_splice_init(&existing_set->init->expressions,
ddb7af
-					 &init->expressions);
ddb7af
-		} else {
ddb7af
-			existing_set->init = set_expr_alloc(&internal_location,
ddb7af
-							    set);
ddb7af
-		}
ddb7af
-	}
ddb7af
-
ddb7af
-	set_to_range(init);
ddb7af
-	list_expr_sort(&init->expressions);
ddb7af
+	set_sort_splice(init, set);
ddb7af
 
ddb7af
 	err = setelem_overlap(msgs, set, init);
ddb7af
 
ddb7af
diff --git a/src/mergesort.c b/src/mergesort.c
ddb7af
index 8e6aac5..dca7142 100644
ddb7af
--- a/src/mergesort.c
ddb7af
+++ b/src/mergesort.c
ddb7af
@@ -70,7 +70,7 @@ static int expr_msort_cmp(const struct expr *e1, const struct expr *e2)
ddb7af
 	return ret;
ddb7af
 }
ddb7af
 
ddb7af
-static void list_splice_sorted(struct list_head *list, struct list_head *head)
ddb7af
+void list_splice_sorted(struct list_head *list, struct list_head *head)
ddb7af
 {
ddb7af
 	struct list_head *h = head->next;
ddb7af
 	struct list_head *l = list->next;
ddb7af
-- 
ddb7af
2.36.1
ddb7af