This is the mail archive of the libc-alpha@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

quicksort and mergesort in glibc



Jeremy reported a few weeks ago (see PR libc/1611):
>  glibc's qsort() always uses merge sort instead of quicksort if it can 
>  malloc() as much memory as the input array size for temporary storage.
>  However, malloc() will happily reserve the requested temporary storage 
>  even if it is backed only by swap space.  As a result, qsort() runs
>  unexpectedly slowly (an order of magnitude slower than predicted!) if
>  the array size is a large fraction of the machine's physical memory.

Ulrich has added already a fix to stdlib/msort to limit the memory
usage to only a quarter of the machine.

I've used his testcase, fixed it and added it to my sort test routines
(available from ftp.suse.com/pub/people/aj/sort-test.tar.gz).  The
sort test routines use a number of different input sequences (see the
source for details).

The test results show that the typical behaviour of mergesort and
quicksort.  For small sets and smaller data types (arrays of ints and
arrays of doubles) mergesort is definitly faster and behaves better.

With 10000 elements quicksort is faster with the 6 byte struct (size
variant 2).  With 2 million elements, quicksort is also faster (on
average!) for doubles - but mergesort is still better for ints.

We could need an optimal break even point for switching from mergesort
(for smaller numbers) to quicksort.  But this depends on machine
charakteristica like memory size, caches, cpu etc.  Currently we're
sorting all arrays with a size of < 1/4 machine memory with mergesort
(mergesort needs an temporary array as large as the input data), and
use quicksort for larger ones.

Is anybody interested in investigating this?  I don't have enough CPU
cycles to burn the next few weeks and therefore ask for volunteers.

If nobody has any more data, I would suggest to use 1/16 instead of
1/4 - but this is still a rule of thumb.

Andreas


P.S. Here're the test results on an Pentium III/500 Mhz with 256 MB
RAM running glibc 2.1.3 and Linux 2.3.99pre3.  I used the core
routines from glibc.  Sort routine 0 is qsort, routine 1 is msort;
Size variant 0 is an int, variant 1 a double and 2 a record with three
ints (only one is used for comparisions).

Testing with 100 elements
Size of arrays: 0 k for int 0 k for double, 1 k for record
No of tests: 200
Size variant: 0
Sort routine 0
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0001
min. cmp.: 528
max. cmp.: 1153
avt. cmp.: 710
Sort routine 1
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0002
min. cmp.: 316
max. cmp.: 316
avt. cmp.: 316
No of tests: 200
Size variant: 1
Sort routine 0
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0001
min. cmp.: 528
max. cmp.: 1153
avt. cmp.: 710
Sort routine 1
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0002
min. cmp.: 316
max. cmp.: 316
avt. cmp.: 316
No of tests: 200
Size variant: 2
Sort routine 0
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0002
min. cmp.: 528
max. cmp.: 1153
avt. cmp.: 710
Sort routine 1
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0001
min. cmp.: 316
max. cmp.: 316
avt. cmp.: 316

Testing with 1023 elements
Size of arrays: 3 k for int 7 k for double, 11 k for record
No of tests: 275
Size variant: 0
Sort routine 0
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0012
min. cmp.: 9146
max. cmp.: 23941
avt. cmp.: 12099
Sort routine 1
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0014
min. cmp.: 5110
max. cmp.: 5110
avt. cmp.: 5110
No of tests: 275
Size variant: 1
Sort routine 0
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0025
min. cmp.: 9146
max. cmp.: 23941
avt. cmp.: 12099
Sort routine 1
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0035
min. cmp.: 5110
max. cmp.: 5110
avt. cmp.: 5110
No of tests: 275
Size variant: 2
Sort routine 0
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0023
min. cmp.: 9146
max. cmp.: 23941
avt. cmp.: 12099
Sort routine 1
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0033
min. cmp.: 5110
max. cmp.: 5110
avt. cmp.: 5110

Testing with 5000 elements
Size of arrays: 19 k for int 39 k for double, 58 k for record
No of tests: 350
Size variant: 0
Sort routine 0
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0094
min. cmp.: 55012
max. cmp.: 168263
avt. cmp.: 73612
Sort routine 1
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0068
min. cmp.: 29804
max. cmp.: 29804
avt. cmp.: 29804
No of tests: 350
Size variant: 1
Sort routine 0
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0147
min. cmp.: 55012
max. cmp.: 168263
avt. cmp.: 73612
Sort routine 1
min. time: 0.0000
max. time: 0.0400
avg. time: 0.0212
min. cmp.: 29804
max. cmp.: 29804
avt. cmp.: 29804
No of tests: 350
Size variant: 2
Sort routine 0
min. time: 0.0000
max. time: 0.0200
avg. time: 0.0122
min. cmp.: 55012
max. cmp.: 168263
avt. cmp.: 73612
Sort routine 1
min. time: 0.0000
max. time: 0.0400
avg. time: 0.0202
min. cmp.: 29804
max. cmp.: 29804
avt. cmp.: 29804

Testing with 10000 elements
Size of arrays: 39 k for int 78 k for double, 117 k for record
No of tests: 375
Size variant: 0
Sort routine 0
min. time: 0.0000
max. time: 0.0400
avg. time: 0.0206
min. cmp.: 120013
max. cmp.: 379273
avt. cmp.: 161980
Sort routine 1
min. time: 0.0000
max. time: 0.0400
avg. time: 0.0133
min. cmp.: 64608
max. cmp.: 64608
avt. cmp.: 64608
No of tests: 375
Size variant: 1
Sort routine 0
min. time: 0.0000
max. time: 0.0600
avg. time: 0.0322
min. cmp.: 120013
max. cmp.: 379273
avt. cmp.: 161980
Sort routine 1
min. time: 0.0200
max. time: 0.0600
avg. time: 0.0448
min. cmp.: 64608
max. cmp.: 64608
avt. cmp.: 64608
No of tests: 375
Size variant: 2
Sort routine 0
min. time: 0.0000
max. time: 0.0600
avg. time: 0.0282
min. cmp.: 120013
max. cmp.: 379273
avt. cmp.: 161980
Sort routine 1
min. time: 0.0200
max. time: 0.0600
avg. time: 0.0434
min. cmp.: 64608
max. cmp.: 64608
avt. cmp.: 64608

Testing with 100000 elements
Size of arrays: 390 k for int 781 k for double, 1171 k for record
No of tests: 450
Size variant: 0
Sort routine 0
min. time: 0.1200
max. time: 0.5800
avg. time: 0.2661
min. cmp.: 1507806
max. cmp.: 5736360
avt. cmp.: 2114881
Sort routine 1
min. time: 0.1200
max. time: 0.2000
avg. time: 0.1529
min. cmp.: 815024
max. cmp.: 815024
avt. cmp.: 815024
No of tests: 450
Size variant: 1
Sort routine 0
min. time: 0.1800
max. time: 0.8600
avg. time: 0.4304
min. cmp.: 1507806
max. cmp.: 5736360
avt. cmp.: 2114881
Sort routine 1
min. time: 0.5000
max. time: 0.6200
avg. time: 0.5712
min. cmp.: 815024
max. cmp.: 815024
avt. cmp.: 815024
No of tests: 450
Size variant: 2
Sort routine 0
min. time: 0.1400
max. time: 0.9000
avg. time: 0.4195
min. cmp.: 1507806
max. cmp.: 5736360
avt. cmp.: 2114881
Sort routine 1
min. time: 0.5000
max. time: 0.6400
avg. time: 0.5661
min. cmp.: 815024
max. cmp.: 815024
avt. cmp.: 815024

Testing with 2000000 elements
Size of arrays: 7812 k for int 15625 k for double, 23437 k for record
No of tests: 550
Size variant: 0
Sort routine 0
min. time: 3.8800
max. time: 18.3200
avg. time: 7.2862
min. cmp.: 39586860
max. cmp.: 177197115
avt. cmp.: 56573208
Sort routine 1
min. time: 3.7400
max. time: 4.3800
avg. time: 3.9830
min. cmp.: 20769984
max. cmp.: 20769984
avt. cmp.: 20769984
No of tests: 550
Size variant: 1
Sort routine 0
min. time: 5.4000
max. time: 27.2600
avg. time: 11.7817
min. cmp.: 39586860
max. cmp.: 177197115
avt. cmp.: 56573208
Sort routine 1
min. time: 14.0000
max. time: 15.0800
avg. time: 14.6400
min. cmp.: 20769984
max. cmp.: 20769984
avt. cmp.: 20769984
No of tests: 550
Size variant: 2
Sort routine 0
min. time: 5.5600
max. time: 30.6800
avg. time: 11.9991
min. cmp.: 39586860
max. cmp.: 177197115
avt. cmp.: 56573208
Sort routine 1
min. time: 14.3600
max. time: 15.5000
avg. time: 14.7696
min. cmp.: 20769984
max. cmp.: 20769984
avt. cmp.: 20769984

-- 
 Andreas Jaeger
  SuSE Labs aj@suse.de
   private aj@arthur.rhein-neckar.de

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]