HTML Preparation code:
x
 
1
<script>
2
  function swap(ary, a, b) {
3
      var t = ary[a];
4
      ary[a] = ary[b];
5
      ary[b] = t;
6
  }
7
  
8
  // Built-in with comparison function (default sorting is "dictionary-style")
9
  function builtin_sort(ary) {
10
      return ary.sort(function(a, b) {
11
          return a - b;
12
      });
13
  }
14
  
15
  // Bubble Sort
16
  function bubble_sort(ary) {
17
      var a, b;
18
      for (a = 0; a < ary.length; a++) {
19
          for (b = a + 1; b < ary.length; b++) {
20
              if (ary[a] > ary[b]) {
21
                  swap(ary, a, b);
22
              }
23
          }
24
      }
25
  
26
      return ary;
27
  }
28
  //Insertion sort
29
  function insertion_sort(ary) {
30
        for(var i=1,l=ary.length;i<l;i++) {
31
            var value = ary[i];
32
            for(var j=i - 1;j>=0;j--) {
33
                if(ary[j] <= value)
34
                    break;
35
                ary[j+1] = ary[j];
36
            }
37
            ary[j+1] = value;
38
        }
39
        return ary;
40
  }
41
  
42
  // Naive (but understandable) quicksort (memory hog)
43
  function naive_quicksort(ary) {
44
      if (ary.length <= 1) {
45
          return ary;
46
      }
47
  
48
      var less = [],
49
          greater = [],
50
          pivot = ary.pop();
51
  
52
      for (var i = 0; i < ary.length; i++) {
53
          if (ary[i] < pivot) {
54
              less.push(ary[i]);
55
          } else {
56
              greater.push(ary[i]);
57
          }
58
      }
59
  
60
      less = naive_quicksort(less);
61
      greater = naive_quicksort(greater);
62
  
63
      return less.concat(pivot, greater);
64
  }
65
  
66
  // In place quicksort
67
  function inplace_quicksort_partition(ary, start, end, pivotIndex) {
68
      var i = start, j = end;
69
      var pivot = ary[pivotIndex];
70
      
71
      while(true) {
72
          while(ary[i] < pivot) {i++};
73
          j--;
74
          while(pivot < ary[j]) {j--};
75
          if(!(i<j)) {
76
              return i;
77
          }
78
          swap(ary,i,j);
79
          i++;
80
     }
81
  }
82
  
83
  function inplace_quicksort(ary, start, end) {
84
      if (start < end - 1) {
85
          var pivotIndex = Math.round((start + end) / 2);
86
  
87
          pivotIndex = inplace_quicksort_partition(ary, start, end, pivotIndex);
88
  
89
          inplace_quicksort(ary, start, pivotIndex - 1);
90
          inplace_quicksort(ary, pivotIndex + 1, end);
91
      }
92
  
93
      return ary;
94
  }
95
  
96
  // Heap sort
97
  function heapSort(ary) {
98
      heapify(ary);
99
  
100
      for (var end = ary.length - 1; end > 0; end--) {
101
          swap(ary, end, 0);
102
          shiftDown(ary, 0, end - 1);
103
      }
104
  
105
      return ary;
106
  }
107
  
108
  function heapify(ary) {
109
      for (var start = (ary.length >> 1) - 1; start >= 0; start--) {
110
          shiftDown(ary, start, ary.length - 1);
111
      }
112
  }
113
  
114
  function shiftDown(ary, start, end) {
115
      var root = start,
116
          child, s;
117
  
118
      while (root * 2 + 1 <= end) {
119
          child = root * 2 + 1;
120
          s = root;
121
  
122
          if (ary[s] < ary[child]) {
123
              s = child;
124
          }
125
  
126
          if (child + 1 <= end && ary[s] < ary[child + 1]) {
127
              s = child + 1;
128
          }
129
  
130
          if (s !== root) {
131
              swap(ary, root, s);
132
              root = s;
133
          } else {
134
              return;
135
          }
136
      }
137
  }
138
  
139
  // Merge sort
140
  function merge_sort(ary) {
141
      if (ary.length <= 1) {
142
          return ary;
143
      }
144
  
145
      var m = ary.length >> 1;
146
  
147
      var left = ary.slice(0, m),
148
          right = ary.slice(m);
149
  
150
      return merge(merge_sort(left), merge_sort(right));
151
  }
152
  
153
  function merge(left, right) {
154
      var result = [],
155
          li = 0, ri = 0;
156
  
157
      while (li < left.length || ri < right.length) {
158
          if (li < left.length && ri < right.length) {
159
              if (left[li] <= right[ri]) {
160
                  result.push(left[li]);
161
                  li++;
162
              } else {
163
                  result.push(right[ri]);
164
                  ri++;
165
              }
166
          } else if (li < left.length) {
167
              result.push(left[li]);
168
              li++;
169
          } else if (ri < right.length) {
170
              result.push(right[ri]);
171
              ri++;
172
          }
173
      }
174
  
175
      return result;
176
  }
177
  
178
  // Shell sort
179
  function shell_sort(ary) {
180
      var inc = Math.round(ary.length / 2),
181
          i, j, t;
182
  
183
      while (inc > 0) {
184
          for (i = inc; i < ary.length; i++) {
185
              t = ary[i];
186
              j = i;
187
              while (j >= inc && ary[j - inc] > t) {
188
                  ary[j] = ary[j - inc];
189
                  j -= inc;
190
              }
191
              ary[j] = t;
192
          }
193
          inc = Math.round(inc / 2.2);
194
      }
195
  
196
      return ary;
197
  }
198
  //Comb Sort (Basically bubblesort with a small modification, but heaps faster)
199
function comb_sort(ary) {
200
    var gap = ary.length;
201
    while(true) {
202
        gap = newgap(gap);
203
        var swapped = false;
204
        for(var i=0,l=ary.length;i<l;i++) {
205
            var j = i + gap;
206
            if(ary[i] < ary[j]) {
207
                swap(ary,i,j);
208
                swapped = true;
209
            }
210
        }
211
        if(gap == 1 && !swapped)
212
             break;
213
    }
214
    return ary;   
215
}
216
function newgap(gap) {
217
    gap = ((gap * 10) / 13) | 0;
218
    if(gap == 9 || gap == 10)
219
        gap = 11;
220
    if(gap < 1)
221
         gap = 1;
222
    return gap;
223
}
224
//faster quicksort using a stack to eliminate recursion, sorting inplace to reduce memory usage, and using insertion sort for small partition sizes
225
function fast_quicksort(ary) {
226
    var stack = [];
227
    var entry = [0,ary.length,2 * Math.floor(Math.log(ary.length)/Math.log(2))];
228
    stack.push(entry);
229
    while(stack.length > 0) {
230
        entry = stack.pop();
231
        var start = entry[0];
232
        var end = entry[1];
233
        var depth = entry[2];
234
        if(depth == 0) {
235
         ary = shell_sort_bound(ary,start,end);
236
         continue;
237
        }
238
        depth--;
239
        var pivot = Math.round((start + end) / 2);
240
            
241
        var pivotNewIndex = inplace_quicksort_partition(ary,start,end, pivot);
242
        if(end - pivotNewIndex > 16) {
243
            entry = [pivotNewIndex,end,depth];
244
            stack.push(entry);
245
        }
246
        if(pivotNewIndex - start > 16) {
247
            entry = [start,pivotNewIndex,depth];
248
            stack.push(entry);
249
        }
250
    }
251
    ary = insertion_sort(ary);
252
    return ary;
253
}
254
function shell_sort_bound(ary,start,end) {
255
      var inc = Math.round((start + end)/2),
256
          i, j, t;
257
  
258
      while (inc >= start) {
259
          for (i = inc; i < end; i++) {
260
              t = ary[i];
261
              j = i;
262
              while (j >= inc && ary[j - inc] > t) {
263
                  ary[j] = ary[j - inc];
264
                  j -= inc;
265
              }
266
              ary[j] = t;
267
          }
268
          inc = Math.round(inc / 2.2);
269
      }
270
  
271
      return ary;
272
  }
273
274
function mSort(list) {
275
                if (list.length < 14) {
276
                    return insertion_sort(list);
277
                }
278
                
279
                var half = Math.floor(list.length / 2);
280
                var a = mSort(list.slice(0, half));
281
                var b = mSort(list.slice(half, list.length));
282
                var aCount = 0;
283
                var bCount = 0;
284
                var returnList = [];
285
                
286
                while (true) {
287
                    if (a[aCount] <= b[bCount]) {
288
                        returnList.push(a[aCount]);
289
                        aCount++;
290
                        if (aCount === a.length) {
291
                            returnList = returnList.concat(b.slice(bCount, b.length));
292
                            break;
293
                        }
294
                    }
295
                    else {
296
                        returnList.push(b[bCount]);
297
                        bCount++;
298
                        if (bCount === b.length) {
299
                            returnList = returnList.concat(a.slice(aCount, a.length));
300
                            break;
301
                        }
302
                    }
303
                }
304
                return returnList;
305
            }
306
  
307
  function bubbleSort(items) {
308
  var length = items.length;
309
  for (var i = 0; i < length; i++) { //Number of passes
310
    for (var j = 0; j < (length - i - 1); j++) { //Notice that j < (length - i)
311
      //Compare the adjacent positions
312
      if(items[j] > items[j+1]) {
313
        //Swap the numbers
314
        var tmp = items[j];  //Temporary variable to hold the current number
315
        items[j] = items[j+1]; //Replace current number with adjacent number
316
        items[j+1] = tmp; //Replace adjacent number with current number
317
      }
318
    }        
319
  }
320
}
321
  
322
  https://stackoverflow.com/a/38979903/8769328
323
  function radixBucketSort (arr) {
324
    var idx1, idx2, idx3, len1, len2, radix, radixKey;
325
    var radices = {}, buckets = {}, num, curr;
326
    var currLen, radixStr, currBucket;
327
328
    len1 = arr.length;
329
    len2 = 10;  // radix sort uses ten buckets
330
331
    // find the relevant radices to process for efficiency        
332
    for (idx1 = 0;idx1 < len1;idx1++) {
333
      radices[arr[idx1].toString().length] = 0;
334
    }
335
336
    // loop for each radix. For each radix we put all the items
337
    // in buckets, and then pull them out of the buckets.
338
    for (radix in radices) {          
339
      // put each array item in a bucket based on its radix value
340
      len1 = arr.length;
341
      for (idx1 = 0;idx1 < len1;idx1++) {
342
        curr = arr[idx1];
343
        // item length is used to find its current radix value
344
        currLen = curr.toString().length;
345
        // only put the item in a radix bucket if the item
346
        // key is as long as the radix
347
        if (currLen >= radix) {
348
          // radix starts from beginning of key, so need to
349
          // adjust to get redix values from start of stringified key
350
          radixKey = curr.toString()[currLen - radix];
351
          // create the bucket if it does not already exist
352
          if (!buckets.hasOwnProperty(radixKey)) {
353
            buckets[radixKey] = [];
354
          }
355
          // put the array value in the bucket
356
          buckets[radixKey].push(curr);          
357
        } else {
358
          if (!buckets.hasOwnProperty('0')) {
359
            buckets['0'] = [];
360
          }
361
          buckets['0'].push(curr);          
362
        }
363
      }
364
      // for current radix, items are in buckets, now put them
365
      // back in the array based on their buckets
366
      // this index moves us through the array as we insert items
367
      idx1 = 0;
368
      // go through all the buckets
369
      for (idx2 = 0;idx2 < len2;idx2++) {
370
        // only process buckets with items
371
        if (buckets[idx2] != null) {
372
          currBucket = buckets[idx2];
373
          // insert all bucket items into array
374
          len1 = currBucket.length;
375
          for (idx3 = 0;idx3 < len1;idx3++) {
376
            arr[idx1++] = currBucket[idx3];
377
          }
378
        }
379
      }
380
      buckets = {};
381
    }
382
  }
383
  
384
  // https://gist.github.com/mourner/a1e0e8f48e0125c541d88199ce0b6479
385
  const last = new Uint32Array(256);
386
  const pointer0 = new Uint32Array(256);
387
  const pointer8 = new Uint32Array(256);
388
  const pointer16 = new Uint32Array(256);
389
  const pointer24 = new Uint32Array(256);
390
391
  function radixSort(arr, start = 0, end = arr.length, shift = 24) {
392
      const ptr =
393
          shift === 0 ? pointer0 :
394
          shift === 8 ? pointer8 :
395
          shift === 16 ? pointer16 : pointer24;
396
397
      for (let x = start; x < end; ++x) last[(arr[x] >> shift) & 0xFF]++;
398
399
      last[0] += start;
400
      ptr[0] = start;
401
      for (let x = 1; x < 256; ++x) {
402
          ptr[x] = last[x - 1];
403
          last[x] += last[x - 1];
404
      }
405
406
      for (let x = 0; x < 256; ++x) {
407
          let i = ptr[x];
408
          while (i !== last[x]) {
409
              let value = arr[i], y;
410
              while ((y = (value >> shift) & 0xFF) !== x) {
411
                  value = arr[ptr[y]];
412
                  swap(arr, i, ptr[y]++);
413
              }
414
              i++;
415
          }
416
          ptr[x] = i;
417
          last[x] = 0;
418
      }
419
420
      if (shift === 0) return;
421
422
      for (let x = 0; x < 256; ++x) {
423
          const i = x > 0 ? ptr[x - 1] : start;
424
          const j = ptr[x];
425
          if (j - i > 64) {
426
              radixSort(arr, i, j, shift - 8);
427
          } else {
428
              insertionSort(arr, i, j);
429
          }
430
      }
431
      return arr;
432
  }
433
434
  function insertionSort(arr, start, end) {
435
      for (let x = start + 1; x < end; ++x) {
436
          for (let y = x; y > start && arr[y - 1] > arr[y]; y--) swap(arr, y, y - 1);
437
      }
438
  }
439
</script>
Script Preparation code:
 
var input = [];
for (var i = 0; i < 1000; i++) {
  input[i] = Math.round(Math.random() * 1000000);
}
Tests:
  • Built-in Sort

     
    builtin_sort(input.slice(0));
  • Naive Quicksort

     
    naive_quicksort(input.slice(0));
  • Inplace Quicksort

     
    inplace_quicksort(input.slice(0), 0, input.length);
  • Heap Sort

     
    heapSort(input.slice(0));
  • Merge Sort

     
    merge_sort(input.slice(0));
  • Shell Sort

     
    shell_sort(input.slice(0));
  • Comb Sort

     
    comb_sort(input.slice(0));
  • Insertion Sort

     
    insertion_sort(input.slice(0));
  • Fast QuickSort

     
    fast_quicksort(input.slice(0));
  • mSort

     
    mSort(input.slice(0));
  • Radix Bucket Sort

     
    radixBucketSort(input.slice(0)) 
  • Bubble Sort

     
    bubbleSort(input.slice(0));
  • Radix Sort

     
    radixSort(input.slice(0));
Rendered benchmark preparation results:

Suite status: <idle, ready to run>

Previous results

Experimental features:

  • Test case name Result
    Built-in Sort
    Naive Quicksort
    Inplace Quicksort
    Heap Sort
    Merge Sort
    Shell Sort
    Comb Sort
    Insertion Sort
    Fast QuickSort
    mSort
    Radix Bucket Sort
    Bubble Sort
    Radix Sort

    Fastest: N/A

    Slowest: N/A

Latest run results:
Run details: (Test run date: 3 years ago)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 Edg/93.0.961.52
Chrome 93 on Mac OS X 10.15.7
View result in a separate tab
Test name Executions per second
Built-in Sort 6050.3 Ops/sec
Naive Quicksort 3695.8 Ops/sec
Inplace Quicksort 25782.3 Ops/sec
Heap Sort 18467.2 Ops/sec
Merge Sort 6554.7 Ops/sec
Shell Sort 11079.6 Ops/sec
Comb Sort 10604.7 Ops/sec
Insertion Sort 3723.8 Ops/sec
Fast QuickSort 31888.7 Ops/sec
mSort 10886.3 Ops/sec
Radix Bucket Sort 5867.4 Ops/sec
Bubble Sort 1196.3 Ops/sec
Radix Sort 22173.5 Ops/sec