Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/util/Arrays/SortingIntBenchmarkTestJMH.java
41152 views
1
/*
2
* Copyright 2015 Goldman Sachs.
3
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
4
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
*
6
* This code is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 2 only, as
8
* published by the Free Software Foundation.
9
*
10
* This code is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* version 2 for more details (a copy is included in the LICENSE file that
14
* accompanied this code).
15
*
16
* You should have received a copy of the GNU General Public License version
17
* 2 along with this work; if not, write to the Free Software Foundation,
18
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21
* or visit www.oracle.com if you need additional information or have any
22
* questions.
23
*/
24
25
import org.openjdk.jmh.annotations.Benchmark;
26
import org.openjdk.jmh.annotations.BenchmarkMode;
27
import org.openjdk.jmh.annotations.Measurement;
28
import org.openjdk.jmh.annotations.Mode;
29
import org.openjdk.jmh.annotations.OutputTimeUnit;
30
import org.openjdk.jmh.annotations.Param;
31
import org.openjdk.jmh.annotations.Scope;
32
import org.openjdk.jmh.annotations.Setup;
33
import org.openjdk.jmh.annotations.State;
34
import org.openjdk.jmh.annotations.Warmup;
35
36
import java.util.ArrayList;
37
import java.util.Arrays;
38
import java.util.HashSet;
39
import java.util.List;
40
import java.util.Random;
41
import java.util.Set;
42
import java.util.concurrent.TimeUnit;
43
44
@State(Scope.Thread)
45
@BenchmarkMode(Mode.Throughput)
46
@OutputTimeUnit(TimeUnit.SECONDS)
47
public class SortingIntBenchmarkTestJMH {
48
private static final int QUICKSORT_THRESHOLD = 286;
49
private static final int MAX_RUN_COUNT = 67;
50
private static final int INSERTION_SORT_THRESHOLD = 47;
51
public static final int MAX_VALUE = 1_000_000;
52
53
@Param({"pairFlipZeroPairFlip", "pairFlipOneHundredPairFlip"
54
, "zeroHi", "hiZeroLow", "hiFlatLow", "identical",
55
"randomDups", "randomNoDups", "sortedReversedSorted", "pairFlip", "endLessThan"})
56
57
public String listType;
58
59
private int[] array;
60
private static final int LIST_SIZE = 10_000_000;
61
public static final int NUMBER_OF_ITERATIONS = 10;
62
63
@Setup
64
public void setUp() {
65
Random random = new Random(123456789012345L);
66
this.array = new int[LIST_SIZE];
67
int threeQuarters = (int) (LIST_SIZE * 0.75);
68
if ("zeroHi".equals(this.listType)) {
69
for (int i = 0; i < threeQuarters; i++) {
70
this.array[i] = 0;
71
}
72
int k = 1;
73
for (int i = threeQuarters; i < LIST_SIZE; i++) {
74
this.array[i] = k;
75
k++;
76
}
77
}
78
else if ("hiFlatLow".equals(this.listType)) {
79
int oneThird = LIST_SIZE / 3;
80
for (int i = 0; i < oneThird; i++) {
81
this.array[i] = i;
82
}
83
int twoThirds = oneThird * 2;
84
int constant = oneThird - 1;
85
for (int i = oneThird; i < twoThirds; i++) {
86
this.array[i] = constant;
87
}
88
for (int i = twoThirds; i < LIST_SIZE; i++) {
89
this.array[i] = constant - i + twoThirds;
90
}
91
}
92
else if ("hiZeroLow".equals(this.listType)) {
93
int oneThird = LIST_SIZE / 3;
94
for (int i = 0; i < oneThird; i++) {
95
this.array[i] = i;
96
}
97
int twoThirds = oneThird * 2;
98
for (int i = oneThird; i < twoThirds; i++) {
99
this.array[i] = 0;
100
}
101
for (int i = twoThirds; i < LIST_SIZE; i++) {
102
this.array[i] = oneThird - i + twoThirds;
103
}
104
}
105
else if ("identical".equals(this.listType)) {
106
for (int i = 0; i < LIST_SIZE; i++) {
107
this.array[i] = 0;
108
}
109
}
110
else if ("randomDups".equals(this.listType)) {
111
for (int i = 0; i < LIST_SIZE; i++) {
112
this.array[i] = random.nextInt(1000);
113
}
114
}
115
else if ("randomNoDups".equals(this.listType)) {
116
Set<Integer> set = new HashSet();
117
while (set.size() < LIST_SIZE + 1) {
118
set.add(random.nextInt());
119
}
120
List<Integer> list = new ArrayList<>(LIST_SIZE);
121
list.addAll(set);
122
for (int i = 0; i < LIST_SIZE; i++) {
123
this.array[i] = list.get(i);
124
}
125
}
126
else if ("sortedReversedSorted".equals(this.listType)) {
127
for (int i = 0; i < LIST_SIZE / 2; i++) {
128
this.array[i] = i;
129
}
130
int num = 0;
131
for (int i = LIST_SIZE / 2; i < LIST_SIZE; i++) {
132
this.array[i] = LIST_SIZE - num;
133
num++;
134
}
135
}
136
else if ("pairFlip".equals(this.listType)) {
137
for (int i = 0; i < LIST_SIZE; i++) {
138
this.array[i] = i;
139
}
140
for (int i = 0; i < LIST_SIZE; i += 2) {
141
int temp = this.array[i];
142
this.array[i] = this.array[i + 1];
143
this.array[i + 1] = temp;
144
}
145
}
146
else if ("endLessThan".equals(this.listType)) {
147
for (int i = 0; i < LIST_SIZE - 1; i++) {
148
this.array[i] = 3;
149
}
150
this.array[LIST_SIZE - 1] = 1;
151
}
152
else if ("pairFlipZeroPairFlip".equals(this.listType)) {
153
//pairflip
154
for (int i = 0; i < 64; i++) {
155
this.array[i] = i;
156
}
157
for (int i = 0; i < 64; i += 2) {
158
int temp = this.array[i];
159
this.array[i] = this.array[i + 1];
160
this.array[i + 1] = temp;
161
}
162
//zero
163
for (int i = 64; i < this.array.length - 64; i++) {
164
this.array[i] = 0;
165
}
166
//pairflip
167
for (int i = this.array.length - 64; i < this.array.length; i++) {
168
this.array[i] = i;
169
}
170
for (int i = this.array.length - 64; i < this.array.length; i += 2) {
171
int temp = this.array[i];
172
this.array[i] = this.array[i + 1];
173
this.array[i + 1] = temp;
174
}
175
}
176
else if ("pairFlipOneHundredPairFlip".equals(this.listType)) {
177
//10, 5
178
for (int i = 0; i < 64; i++) {
179
if (i % 2 == 0) {
180
this.array[i] = 10;
181
}
182
else {
183
this.array[i] = 5;
184
}
185
}
186
187
//100
188
for (int i = 64; i < this.array.length - 64; i++) {
189
this.array[i] = 100;
190
}
191
192
//10, 5
193
for (int i = this.array.length - 64; i < this.array.length; i++) {
194
if (i % 2 == 0) {
195
this.array[i] = 10;
196
}
197
else {
198
this.array[i] = 5;
199
}
200
}
201
}
202
}
203
204
@Warmup(iterations = 20)
205
@Measurement(iterations = 10)
206
@Benchmark
207
public void sortNewWay() {
208
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
209
SortingIntTestJMH.sort(this.array, 0, this.array.length - 1, null, 0, 0);
210
}
211
}
212
213
@Warmup(iterations = 20)
214
@Measurement(iterations = 10)
215
@Benchmark
216
public void sortCurrentWay() {
217
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++) {
218
Arrays.sort(this.array);
219
}
220
}
221
222
static void sort(int[] a, int left, int right,
223
int[] work, int workBase, int workLen) {
224
// Use Quicksort on small arrays
225
if (right - left < QUICKSORT_THRESHOLD) {
226
SortingIntTestJMH.sort(a, left, right, true);
227
return;
228
}
229
230
/*
231
* Index run[i] is the start of i-th run
232
* (ascending or descending sequence).
233
*/
234
int[] run = new int[MAX_RUN_COUNT + 1];
235
int count = 0;
236
run[0] = left;
237
238
// Check if the array is nearly sorted
239
for (int k = left; k < right; run[count] = k) {
240
while (k < right && a[k] == a[k + 1])
241
k++;
242
if (k == right) break;
243
if (a[k] < a[k + 1]) { // ascending
244
while (++k <= right && a[k - 1] <= a[k]) ;
245
}
246
else if (a[k] > a[k + 1]) { // descending
247
while (++k <= right && a[k - 1] >= a[k]) ;
248
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
249
int t = a[lo];
250
a[lo] = a[hi];
251
a[hi] = t;
252
}
253
}
254
if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
255
count--;
256
}
257
/*
258
* The array is not highly structured,
259
* use Quicksort instead of merge sort.
260
*/
261
if (++count == MAX_RUN_COUNT) {
262
sort(a, left, right, true);
263
return;
264
}
265
}
266
267
// Check special cases
268
// Implementation note: variable "right" is increased by 1.
269
if (run[count] == right++) {
270
run[++count] = right;
271
}
272
if (count <= 1) { // The array is already sorted
273
return;
274
}
275
276
// Determine alternation base for merge
277
byte odd = 0;
278
for (int n = 1; (n <<= 1) < count; odd ^= 1) {
279
}
280
281
// Use or create temporary array b for merging
282
int[] b; // temp array; alternates with a
283
int ao, bo; // array offsets from 'left'
284
int blen = right - left; // space needed for b
285
if (work == null || workLen < blen || workBase + blen > work.length) {
286
work = new int[blen];
287
workBase = 0;
288
}
289
if (odd == 0) {
290
System.arraycopy(a, left, work, workBase, blen);
291
b = a;
292
bo = 0;
293
a = work;
294
ao = workBase - left;
295
}
296
else {
297
b = work;
298
ao = 0;
299
bo = workBase - left;
300
}
301
302
// Merging
303
for (int last; count > 1; count = last) {
304
for (int k = (last = 0) + 2; k <= count; k += 2) {
305
int hi = run[k], mi = run[k - 1];
306
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
307
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
308
b[i + bo] = a[p++ + ao];
309
}
310
else {
311
b[i + bo] = a[q++ + ao];
312
}
313
}
314
run[++last] = hi;
315
}
316
if ((count & 1) != 0) {
317
for (int i = right, lo = run[count - 1]; --i >= lo;
318
b[i + bo] = a[i + ao]
319
) {
320
}
321
run[++last] = right;
322
}
323
int[] t = a;
324
a = b;
325
b = t;
326
int o = ao;
327
ao = bo;
328
bo = o;
329
}
330
}
331
332
private static void sort(int[] a, int left, int right, boolean leftmost) {
333
int length = right - left + 1;
334
335
// Use insertion sort on tiny arrays
336
if (length < INSERTION_SORT_THRESHOLD) {
337
if (leftmost) {
338
/*
339
* Traditional (without sentinel) insertion sort,
340
* optimized for server VM, is used in case of
341
* the leftmost part.
342
*/
343
for (int i = left, j = i; i < right; j = ++i) {
344
int ai = a[i + 1];
345
while (ai < a[j]) {
346
a[j + 1] = a[j];
347
if (j-- == left) {
348
break;
349
}
350
}
351
a[j + 1] = ai;
352
}
353
}
354
else {
355
/*
356
* Skip the longest ascending sequence.
357
*/
358
do {
359
if (left >= right) {
360
return;
361
}
362
}
363
while (a[++left] >= a[left - 1]);
364
365
/*
366
* Every element from adjoining part plays the role
367
* of sentinel, therefore this allows us to avoid the
368
* left range check on each iteration. Moreover, we use
369
* the more optimized algorithm, so called pair insertion
370
* sort, which is faster (in the context of Quicksort)
371
* than traditional implementation of insertion sort.
372
*/
373
for (int k = left; ++left <= right; k = ++left) {
374
int a1 = a[k], a2 = a[left];
375
376
if (a1 < a2) {
377
a2 = a1;
378
a1 = a[left];
379
}
380
while (a1 < a[--k]) {
381
a[k + 2] = a[k];
382
}
383
a[++k + 1] = a1;
384
385
while (a2 < a[--k]) {
386
a[k + 1] = a[k];
387
}
388
a[k + 1] = a2;
389
}
390
int last = a[right];
391
392
while (last < a[--right]) {
393
a[right + 1] = a[right];
394
}
395
a[right + 1] = last;
396
}
397
return;
398
}
399
400
// Inexpensive approximation of length / 7
401
int seventh = (length >> 3) + (length >> 6) + 1;
402
403
/*
404
* Sort five evenly spaced elements around (and including) the
405
* center element in the range. These elements will be used for
406
* pivot selection as described below. The choice for spacing
407
* these elements was empirically determined to work well on
408
* a wide variety of inputs.
409
*/
410
int e3 = (left + right) >>> 1; // The midpoint
411
int e2 = e3 - seventh;
412
int e1 = e2 - seventh;
413
int e4 = e3 + seventh;
414
int e5 = e4 + seventh;
415
416
// Sort these elements using insertion sort
417
if (a[e2] < a[e1]) {
418
int t = a[e2];
419
a[e2] = a[e1];
420
a[e1] = t;
421
}
422
423
if (a[e3] < a[e2]) {
424
int t = a[e3];
425
a[e3] = a[e2];
426
a[e2] = t;
427
if (t < a[e1]) {
428
a[e2] = a[e1];
429
a[e1] = t;
430
}
431
}
432
if (a[e4] < a[e3]) {
433
int t = a[e4];
434
a[e4] = a[e3];
435
a[e3] = t;
436
if (t < a[e2]) {
437
a[e3] = a[e2];
438
a[e2] = t;
439
if (t < a[e1]) {
440
a[e2] = a[e1];
441
a[e1] = t;
442
}
443
}
444
}
445
if (a[e5] < a[e4]) {
446
int t = a[e5];
447
a[e5] = a[e4];
448
a[e4] = t;
449
if (t < a[e3]) {
450
a[e4] = a[e3];
451
a[e3] = t;
452
if (t < a[e2]) {
453
a[e3] = a[e2];
454
a[e2] = t;
455
if (t < a[e1]) {
456
a[e2] = a[e1];
457
a[e1] = t;
458
}
459
}
460
}
461
}
462
463
// Pointers
464
int less = left; // The index of the first element of center part
465
int great = right; // The index before the first element of right part
466
467
if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {
468
/*
469
* Use the second and fourth of the five sorted elements as pivots.
470
* These values are inexpensive approximations of the first and
471
* second terciles of the array. Note that pivot1 <= pivot2.
472
*/
473
int pivot1 = a[e2];
474
int pivot2 = a[e4];
475
476
/*
477
* The first and the last elements to be sorted are moved to the
478
* locations formerly occupied by the pivots. When partitioning
479
* is complete, the pivots are swapped back into their final
480
* positions, and excluded from subsequent sorting.
481
*/
482
a[e2] = a[left];
483
a[e4] = a[right];
484
485
/*
486
* Skip elements, which are less or greater than pivot values.
487
*/
488
while (a[++less] < pivot1) {
489
}
490
while (a[--great] > pivot2) {
491
}
492
493
/*
494
* Partitioning:
495
*
496
* left part center part right part
497
* +--------------------------------------------------------------+
498
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
499
* +--------------------------------------------------------------+
500
* ^ ^ ^
501
* | | |
502
* less k great
503
*
504
* Invariants:
505
*
506
* all in (left, less) < pivot1
507
* pivot1 <= all in [less, k) <= pivot2
508
* all in (great, right) > pivot2
509
*
510
* Pointer k is the first index of ?-part.
511
*/
512
outer:
513
for (int k = less - 1; ++k <= great; ) {
514
int ak = a[k];
515
if (ak < pivot1) { // Move a[k] to left part
516
a[k] = a[less];
517
/*
518
* Here and below we use "a[i] = b; i++;" instead
519
* of "a[i++] = b;" due to performance issue.
520
*/
521
a[less] = ak;
522
++less;
523
}
524
else if (ak > pivot2) { // Move a[k] to right part
525
while (a[great] > pivot2) {
526
if (great-- == k) {
527
break outer;
528
}
529
}
530
if (a[great] < pivot1) { // a[great] <= pivot2
531
a[k] = a[less];
532
a[less] = a[great];
533
++less;
534
}
535
else { // pivot1 <= a[great] <= pivot2
536
a[k] = a[great];
537
}
538
/*
539
* Here and below we use "a[i] = b; i--;" instead
540
* of "a[i--] = b;" due to performance issue.
541
*/
542
a[great] = ak;
543
--great;
544
}
545
}
546
547
// Swap pivots into their final positions
548
a[left] = a[less - 1];
549
a[less - 1] = pivot1;
550
a[right] = a[great + 1];
551
a[great + 1] = pivot2;
552
553
// Sort left and right parts recursively, excluding known pivots
554
SortingIntTestJMH.sort(a, left, less - 2, leftmost);
555
SortingIntTestJMH.sort(a, great + 2, right, false);
556
557
/*
558
* If center part is too large (comprises > 4/7 of the array),
559
* swap internal pivot values to ends.
560
*/
561
if (less < e1 && e5 < great) {
562
/*
563
* Skip elements, which are equal to pivot values.
564
*/
565
while (a[less] == pivot1) {
566
++less;
567
}
568
569
while (a[great] == pivot2) {
570
--great;
571
}
572
573
/*
574
* Partitioning:
575
*
576
* left part center part right part
577
* +----------------------------------------------------------+
578
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
579
* +----------------------------------------------------------+
580
* ^ ^ ^
581
* | | |
582
* less k great
583
*
584
* Invariants:
585
*
586
* all in (*, less) == pivot1
587
* pivot1 < all in [less, k) < pivot2
588
* all in (great, *) == pivot2
589
*
590
* Pointer k is the first index of ?-part.
591
*/
592
outer:
593
for (int k = less - 1; ++k <= great; ) {
594
int ak = a[k];
595
if (ak == pivot1) { // Move a[k] to left part
596
a[k] = a[less];
597
a[less] = ak;
598
++less;
599
}
600
else if (ak == pivot2) { // Move a[k] to right part
601
while (a[great] == pivot2) {
602
if (great-- == k) {
603
break outer;
604
}
605
}
606
if (a[great] == pivot1) { // a[great] < pivot2
607
a[k] = a[less];
608
/*
609
* Even though a[great] equals to pivot1, the
610
* assignment a[less] = pivot1 may be incorrect,
611
* if a[great] and pivot1 are floating-point zeros
612
* of different signs. Therefore in float and
613
* double sorting methods we have to use more
614
* accurate assignment a[less] = a[great].
615
*/
616
a[less] = pivot1;
617
++less;
618
}
619
else { // pivot1 < a[great] < pivot2
620
a[k] = a[great];
621
}
622
a[great] = ak;
623
--great;
624
}
625
}
626
}
627
628
// Sort center part recursively
629
SortingIntTestJMH.sort(a, less, great, false);
630
}
631
else { // Partitioning with one pivot
632
/*
633
* Use the third of the five sorted elements as pivot.
634
* This value is inexpensive approximation of the median.
635
*/
636
int pivot = a[e3];
637
638
/*
639
* Partitioning degenerates to the traditional 3-way
640
* (or "Dutch National Flag") schema:
641
*
642
* left part center part right part
643
* +-------------------------------------------------+
644
* | < pivot | == pivot | ? | > pivot |
645
* +-------------------------------------------------+
646
* ^ ^ ^
647
* | | |
648
* less k great
649
*
650
* Invariants:
651
*
652
* all in (left, less) < pivot
653
* all in [less, k) == pivot
654
* all in (great, right) > pivot
655
*
656
* Pointer k is the first index of ?-part.
657
*/
658
for (int k = less; k <= great; ++k) {
659
if (a[k] == pivot) {
660
continue;
661
}
662
int ak = a[k];
663
if (ak < pivot) { // Move a[k] to left part
664
a[k] = a[less];
665
a[less] = ak;
666
++less;
667
}
668
else { // a[k] > pivot - Move a[k] to right part
669
while (a[great] > pivot) {
670
--great;
671
}
672
if (a[great] < pivot) { // a[great] <= pivot
673
a[k] = a[less];
674
a[less] = a[great];
675
++less;
676
}
677
else { // a[great] == pivot
678
/*
679
* Even though a[great] equals to pivot, the
680
* assignment a[k] = pivot may be incorrect,
681
* if a[great] and pivot are floating-point
682
* zeros of different signs. Therefore in float
683
* and double sorting methods we have to use
684
* more accurate assignment a[k] = a[great].
685
*/
686
a[k] = pivot;
687
}
688
a[great] = ak;
689
--great;
690
}
691
}
692
693
/*
694
* Sort left and right parts recursively.
695
* All elements from center part are equal
696
* and, therefore, already sorted.
697
*/
698
SortingIntTestJMH.sort(a, left, less - 1, leftmost);
699
SortingIntTestJMH.sort(a, great + 1, right, false);
700
}
701
}
702
703
private static void swap(int[] arr, int i, int j) {
704
int tmp = arr[i];
705
arr[i] = arr[j];
706
arr[j] = tmp;
707
}
708
}
709
710