Skip to content

Commit 03bf835

Browse files
committed
stdlib: Remove use of mergesort on qsort (BZ 21719)
This patch removes the mergesort optimization on qsort implementation and uses the introsort instead. The mergesort implementation has some issues: - It is as-safe only for certain types sizes (if total size is less than 1 KB with large element sizes also forcing memory allocation) which contradicts the function documentation. Although not required by the C standard, it is preferable and doable to have an O(1) space implementation. - The malloc for certain element size and element number adds arbitrary latency (might even be worse if malloc is interposed). - To avoid trigger swap from memory allocation the implementation relies on system information that might be virtualized (for instance VMs with overcommit memory) which might lead to potentially use of swap even if system advertise more memory than actually has. The check also have the downside of issuing syscalls where none is expected (although only once per execution). - The mergesort is suboptimal on an already sorted array (BZ#21719). The introsort implementation is already optimized to use constant extra space (due to the limit of total number of elements from maximum VM size) and thus can be used to avoid the malloc usage issues. Resulting performance is slower due the usage of qsort, specially in the worst-case scenario (partialy or sorted arrays) and due the fact mergesort uses a slight improved swap operations. This change also renders the BZ#21719 fix unrequired (since it is meant to fix the sorted input performance degradation for mergesort). The manual is also updated to indicate the function is now async-cancel safe. Checked on x86_64-linux-gnu. Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
1 parent 274a46c commit 03bf835

File tree

7 files changed

+16
-323
lines changed

7 files changed

+16
-323
lines changed

include/stdlib.h

-2
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ extern int __posix_openpt (int __oflag) attribute_hidden;
149149
extern int __add_to_environ (const char *name, const char *value,
150150
const char *combines, int replace)
151151
attribute_hidden;
152-
extern void _quicksort (void *const pbase, size_t total_elems,
153-
size_t size, __compar_d_fn_t cmp, void *arg);
154152

155153
extern int __on_exit (void (*__func) (int __status, void *__arg), void *__arg);
156154

manual/argp.texi

+1-1
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ for options, bad phase of the moon, etc.
735735
@c hol_set_group ok
736736
@c hol_find_entry ok
737737
@c hol_sort @mtslocale @acucorrupt
738-
@c qsort dup @acucorrupt
738+
@c qsort dup
739739
@c hol_entry_qcmp @mtslocale
740740
@c hol_entry_cmp @mtslocale
741741
@c group_cmp ok

manual/locale.texi

+1-2
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ The symbols in this section are defined in the header file @file{locale.h}.
253253
@c calculate_head_size ok
254254
@c __munmap ok
255255
@c compute_hashval ok
256-
@c qsort dup @acucorrupt
256+
@c qsort dup
257257
@c rangecmp ok
258258
@c malloc @ascuheap @acsmem
259259
@c strdup @ascuheap @acsmem
@@ -275,7 +275,6 @@ The symbols in this section are defined in the header file @file{locale.h}.
275275
@c realloc @ascuheap @acsmem
276276
@c realloc @ascuheap @acsmem
277277
@c fclose @ascuheap @asulock @acsmem @acsfd @aculock
278-
@c qsort @ascuheap @acsmem
279278
@c alias_compare dup
280279
@c libc_lock_unlock @aculock
281280
@c _nl_explode_name @ascuheap @acsmem

manual/search.texi

+3-4
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ To sort an array using an arbitrary comparison function, use the
159159

160160
@deftypefun void qsort (void *@var{array}, size_t @var{count}, size_t @var{size}, comparison_fn_t @var{compare})
161161
@standards{ISO, stdlib.h}
162-
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
162+
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
163163
The @code{qsort} function sorts the array @var{array}. The array
164164
contains @var{count} elements, each of which is of size @var{size}.
165165

@@ -199,9 +199,8 @@ Functions}):
199199
The @code{qsort} function derives its name from the fact that it was
200200
originally implemented using the ``quick sort'' algorithm.
201201

202-
The implementation of @code{qsort} in this library might not be an
203-
in-place sort and might thereby use an extra amount of memory to store
204-
the array.
202+
The implementation of @code{qsort} in this library is an in-place sort
203+
and uses a constant extra space (allocated on the stack).
205204
@end deftypefun
206205

207206
@node Search/Sort Example

stdlib/Makefile

-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ routines := \
9696
mbtowc \
9797
mrand48 \
9898
mrand48_r \
99-
msort \
10099
nrand48 \
101100
nrand48_r \
102101
old_atexit \
@@ -380,7 +379,6 @@ generated += \
380379
# generated
381380

382381
CFLAGS-bsearch.c += $(uses-callbacks)
383-
CFLAGS-msort.c += $(uses-callbacks)
384382
CFLAGS-qsort.c += $(uses-callbacks)
385383
CFLAGS-system.c += -fexceptions
386384
CFLAGS-system.os = -fomit-frame-pointer

stdlib/msort.c

-309
This file was deleted.

0 commit comments

Comments
 (0)