Skip to content

Commit 7a3775e

Browse files
rscharfegitster
authored andcommitted
mergesort: unify ranks loops
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6cd33dc commit 7a3775e

File tree

1 file changed

+15
-16
lines changed

1 file changed

+15
-16
lines changed

mergesort.c

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,28 +57,27 @@ void *llist_mergesort(void *list,
5757
{
5858
void *ranks[bitsizeof(void *)];
5959
size_t n = 0;
60-
int i;
6160

62-
while (list) {
61+
if (!list)
62+
return NULL;
63+
64+
for (;;) {
65+
int i;
66+
size_t m;
6367
void *next = get_next_fn(list);
6468
if (next)
6569
set_next_fn(list, NULL);
66-
for (i = 0; n & ((size_t)1 << i); i++)
67-
list = llist_merge(ranks[i], list, get_next_fn,
68-
set_next_fn, compare_fn);
70+
for (i = 0, m = n;; i++, m >>= 1) {
71+
if (m & 1)
72+
list = llist_merge(ranks[i], list, get_next_fn,
73+
set_next_fn, compare_fn);
74+
else if (next)
75+
break;
76+
else if (!m)
77+
return list;
78+
}
6979
n++;
7080
ranks[i] = list;
7181
list = next;
7282
}
73-
74-
for (i = 0; n; i++, n >>= 1) {
75-
if (!(n & 1))
76-
continue;
77-
if (list)
78-
list = llist_merge(ranks[i], list, get_next_fn,
79-
set_next_fn, compare_fn);
80-
else
81-
list = ranks[i];
82-
}
83-
return list;
8483
}

0 commit comments

Comments
 (0)