git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 01/10] mergesort: unify ranks loops

From
René Scharfe <l.s.r@web.de>
Date
Jul 16, 2022, 16:52 UTC
Message-ID
<50b229e9-46b7-fdd1-3f68-de8dd4acf811@web.de>
In-Reply-To
<4d7cd286-398e-215c-f2bd-aa7e8207be4f@web.de>

llist_mergesort() has a loop for adding a new element to the ranks array and another one for rolling up said array into a single sorted list at the end. We can merge them, so that adding the last element rolls up the whole array. Handle the empty list before the main loop now because list can't be NULL anymore inside the loop.

The result is shorter code and significantly less object text:

main: __TEXT __DATA __OBJC others dec hex 652 0 0 4651 5303 14b7 mergesort.o

With this patch: __TEXT __DATA __OBJC others dec hex 412 0 0 3441 3853 f0d mergesort.o

Why is the change so big? The reduction is amplified by llist_merge() being inlined both before and after.

Performance stays basically the same:

main: 0071.12: llist_mergesort() unsorted 0.24(0.22+0.01) 0071.14: llist_mergesort() sorted 0.12(0.10+0.01) 0071.16: llist_mergesort() reversed 0.12(0.10+0.01)

Benchmark 1: t/helper/test-tool mergesort test
  Time (mean ± σ):     109.0 ms ±   0.3 ms    [User: 107.4 ms, System: 1.1 ms]
  Range (min … max):   108.7 ms … 109.6 ms    27 runs

With this patch: 0071.12: llist_mergesort() unsorted 0.24(0.22+0.01) 0071.14: llist_mergesort() sorted 0.12(0.10+0.01) 0071.16: llist_mergesort() reversed 0.12(0.10+0.01)

Benchmark 1: t/helper/test-tool mergesort test
  Time (mean ± σ):     109.2 ms ±   0.2 ms    [User: 107.5 ms, System: 1.1 ms]
  Range (min … max):   108.9 ms … 109.6 ms    27 runs
Signed-off-by: René Scharfe <l.s.r@web.de>
---
 mergesort.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/mergesort.c b/mergesort.c
index bd9c6ef8ee..92150c4101 100644
--- a/mergesort.c
+++ b/mergesort.c
@@ -57,28 +57,27 @@ void *llist_mergesort(void *list,
 {
 	void *ranks[bitsizeof(void *)];
 	size_t n = 0;
-	int i;

-	while (list) {
+	if (!list)
+		return NULL;
+
+	for (;;) {
+		int i;
+		size_t m;
 		void *next = get_next_fn(list);
 		if (next)
 			set_next_fn(list, NULL);
-		for (i = 0; n & ((size_t)1 << i); i++)
-			list = llist_merge(ranks[i], list, get_next_fn,
-					   set_next_fn, compare_fn);
+		for (i = 0, m = n;; i++, m >>= 1) {
+			if (m & 1)
+				list = llist_merge(ranks[i], list, get_next_fn,
+						   set_next_fn, compare_fn);
+			else if (next)
+				break;
+			else if (!m)
+				return list;
+		}
 		n++;
 		ranks[i] = list;
 		list = next;
 	}
-
-	for (i = 0; n; i++, n >>= 1) {
-		if (!(n & 1))
-			continue;
-		if (list)
-			list = llist_merge(ranks[i], list, get_next_fn,
-					   set_next_fn, compare_fn);
-		else
-			list = ranks[i];
-	}
-	return list;
 }
--
2.37.1
Previous: René ScharfeNext: René Scharfe
Message 2 of 15 in “typed sort of linked lists”
  1. 00/10 typed sort of linked listsRené Scharfe, Jul 16, 2022
  2. 01/10 mergesort: unify ranks loopsRené Scharfe, Jul 16, 2022
  3. 02/10 mergesort: tighten merge loopRené Scharfe, Jul 16, 2022
  4. 03/10 mergesort: add macros for typed sort of linked listsRené Scharfe, Jul 16, 2022
  5. 04/10 test-mergesort: use DEFINE_LIST_SORT_DEBUGRené Scharfe, Jul 16, 2022
  6. 05/10 test-mergesort: use DEFINE_LIST_SORTRené Scharfe, Jul 16, 2022
  7. 06/10 blame: use DEFINE_LIST_SORTRené Scharfe, Jul 16, 2022
  8. 07/10 commit: use DEFINE_LIST_SORTRené Scharfe, Jul 16, 2022
  9. 08/10 fetch-pack: use DEFINE_LIST_SORTRené Scharfe, Jul 16, 2022
  10. 09/10 packfile: use DEFINE_LIST_SORTRené Scharfe, Jul 16, 2022
  11. 10/10 mergesort: remove llist_mergesort()René Scharfe, Jul 16, 2022
  12. Junio C HamanoJul 17, 2022
  13. Junio C HamanoJul 25, 2022
  14. Derrick StoleeJul 25, 2022
  15. Junio C HamanoJul 25, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.