1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.rng.examples.jmh.simple;
19
20 import org.apache.commons.rng.UniformRandomProvider;
21 import org.apache.commons.rng.simple.RandomSource;
22 import org.openjdk.jmh.annotations.Benchmark;
23 import org.openjdk.jmh.annotations.BenchmarkMode;
24 import org.openjdk.jmh.annotations.Fork;
25 import org.openjdk.jmh.annotations.Measurement;
26 import org.openjdk.jmh.annotations.Mode;
27 import org.openjdk.jmh.annotations.OutputTimeUnit;
28 import org.openjdk.jmh.annotations.Param;
29 import org.openjdk.jmh.annotations.Scope;
30 import org.openjdk.jmh.annotations.Setup;
31 import org.openjdk.jmh.annotations.State;
32 import org.openjdk.jmh.annotations.Threads;
33 import org.openjdk.jmh.annotations.Warmup;
34
35 import java.util.concurrent.TimeUnit;
36 import java.util.concurrent.locks.Lock;
37 import java.util.concurrent.locks.ReentrantLock;
38
39
40
41
42
43
44
45 @BenchmarkMode(Mode.AverageTime)
46 @OutputTimeUnit(TimeUnit.NANOSECONDS)
47 @Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
48 @Measurement(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
49 @State(Scope.Benchmark)
50 @Fork(value = 1, jvmArgs = { "-server", "-Xms512M", "-Xmx512M" })
51 public class SeedArrayGenerationPerformance {
52
53
54
55
56
57
58 private static final ReentrantLock UNFAIR_LOCK = new ReentrantLock(false);
59
60
61
62
63
64
65
66 private static final ReentrantLock FAIR_LOCK = new ReentrantLock(true);
67
68
69 private int[] intValue;
70
71
72 private long[] longValue;
73
74
75
76
77 @State(Scope.Benchmark)
78 public static class SeedRandomSources {
79
80
81
82
83 @Param({"WELL_44497_B",
84 "XOR_SHIFT_1024_S_PHI",
85 })
86 private String randomSourceName;
87
88
89 private UniformRandomProvider generator;
90
91
92
93
94
95
96 public UniformRandomProvider getGenerator() {
97 return generator;
98 }
99
100
101
102
103 @Setup
104 public void setup() {
105 generator = RandomSource.create(RandomSource.valueOf(randomSourceName));
106 }
107 }
108
109
110
111
112 @State(Scope.Benchmark)
113 public static class SeedSizes {
114
115 @Param({"2", "4", "8", "16", "32", "64", "128"})
116 private int size;
117
118
119
120
121
122
123 public int getSize() {
124 return size;
125 }
126 }
127
128
129
130
131
132 @State(Scope.Benchmark)
133 public static class TestSizes {
134
135 @Param({"2", "4", "8", "16", "32", "64", "128"})
136 private int size;
137
138
139 @Param({"2", "4", "8", "16", "32", "64", "128"})
140 private int blockSize;
141
142
143
144
145
146
147 public int getSize() {
148 return size;
149 }
150
151
152
153
154 public int getBlockSize() {
155 return blockSize;
156 }
157
158
159
160
161
162 @Setup
163 public void setup() {
164 if (getBlockSize() > getSize()) {
165 throw new AssertionError("Skipping benchmark: Block size is above seed size");
166 }
167 }
168 }
169
170
171
172
173
174
175
176 private static int nextInt(UniformRandomProvider rng) {
177 synchronized (rng) {
178 return rng.nextInt();
179 }
180 }
181
182
183
184
185
186
187
188 private static long nextLong(UniformRandomProvider rng) {
189 synchronized (rng) {
190 return rng.nextLong();
191 }
192 }
193
194
195
196
197
198
199
200
201
202
203 private static void nextInt(UniformRandomProvider rng, int[] array, int start, int end) {
204 synchronized (rng) {
205 for (int i = start; i < end; i++) {
206 array[i] = rng.nextInt();
207 }
208 }
209 }
210
211
212
213
214
215
216
217
218
219
220 private static void nextLong(UniformRandomProvider rng, long[] array, int start, int end) {
221 synchronized (rng) {
222 for (int i = start; i < end; i++) {
223 array[i] = rng.nextLong();
224 }
225 }
226 }
227
228
229
230
231
232
233
234
235 private static int nextInt(Lock lock, UniformRandomProvider rng) {
236 lock.lock();
237 try {
238 return rng.nextInt();
239 } finally {
240 lock.unlock();
241 }
242 }
243
244
245
246
247
248
249
250
251 private static long nextLong(Lock lock, UniformRandomProvider rng) {
252 lock.lock();
253 try {
254 return rng.nextLong();
255 } finally {
256 lock.unlock();
257 }
258 }
259
260
261
262
263
264
265
266
267
268
269
270 private static void nextInt(Lock lock, UniformRandomProvider rng, int[] array, int start, int end) {
271 lock.lock();
272 try {
273 for (int i = start; i < end; i++) {
274 array[i] = rng.nextInt();
275 }
276 } finally {
277 lock.unlock();
278 }
279 }
280
281
282
283
284
285
286
287
288
289
290
291 private static void nextLong(Lock lock, UniformRandomProvider rng, long[] array, int start, int end) {
292 lock.lock();
293 try {
294 for (int i = start; i < end; i++) {
295 array[i] = rng.nextLong();
296 }
297 } finally {
298 lock.unlock();
299 }
300 }
301
302
303
304
305 @Benchmark
306 public void baselineVoid() {
307
308 }
309
310
311
312
313
314
315 @Benchmark
316 public int[] baselineIntArray() {
317 return intValue;
318 }
319
320
321
322
323
324
325 @Benchmark
326 public long[] baselineLongArray() {
327 return longValue;
328 }
329
330
331
332
333
334
335
336
337
338
339
340 @Benchmark
341 public int[] createIntArraySeed(SeedRandomSources sources, SeedSizes sizes) {
342 final UniformRandomProvider rng = sources.getGenerator();
343 final int[] seed = new int[sizes.getSize()];
344 for (int i = 0; i < seed.length; i++) {
345 seed[i] = rng.nextInt();
346 }
347 return seed;
348 }
349
350
351
352
353
354
355 @Benchmark
356 public long[] createLongArraySeed(SeedRandomSources sources, SeedSizes sizes) {
357 final UniformRandomProvider rng = sources.getGenerator();
358 final long[] seed = new long[sizes.getSize()];
359 for (int i = 0; i < seed.length; i++) {
360 seed[i] = rng.nextLong();
361 }
362 return seed;
363 }
364
365
366
367
368
369
370 @Benchmark
371 public int[] Threads1_createIntArraySeed_Sync(SeedRandomSources sources, SeedSizes sizes) {
372 final UniformRandomProvider rng = sources.getGenerator();
373 final int[] seed = new int[sizes.getSize()];
374 for (int i = 0; i < seed.length; i++) {
375 seed[i] = nextInt(rng);
376 }
377 return seed;
378 }
379
380
381
382
383
384
385 @Benchmark
386 public long[] Threads1_createLongArraySeed_Sync(SeedRandomSources sources, SeedSizes sizes) {
387 final UniformRandomProvider rng = sources.getGenerator();
388 final long[] seed = new long[sizes.getSize()];
389 for (int i = 0; i < seed.length; i++) {
390 seed[i] = nextLong(rng);
391 }
392 return seed;
393 }
394
395
396
397
398
399
400 @Benchmark
401 public int[] Threads1_createIntArraySeed_UnfairLock(SeedRandomSources sources, SeedSizes sizes) {
402 final UniformRandomProvider rng = sources.getGenerator();
403 final int[] seed = new int[sizes.getSize()];
404 for (int i = 0; i < seed.length; i++) {
405 seed[i] = nextInt(UNFAIR_LOCK, rng);
406 }
407 return seed;
408 }
409
410
411
412
413
414
415 @Benchmark
416 public long[] Threads1_createLongArraySeed_UnfairLock(SeedRandomSources sources, SeedSizes sizes) {
417 final UniformRandomProvider rng = sources.getGenerator();
418 final long[] seed = new long[sizes.getSize()];
419 for (int i = 0; i < seed.length; i++) {
420 seed[i] = nextLong(UNFAIR_LOCK, rng);
421 }
422 return seed;
423 }
424
425
426
427
428
429
430 @Benchmark
431 public int[] Threads1_createIntArraySeed_FairLock(SeedRandomSources sources, SeedSizes sizes) {
432 final UniformRandomProvider rng = sources.getGenerator();
433 final int[] seed = new int[sizes.getSize()];
434 for (int i = 0; i < seed.length; i++) {
435 seed[i] = nextInt(FAIR_LOCK, rng);
436 }
437 return seed;
438 }
439
440
441
442
443
444
445 @Benchmark
446 public long[] Threads1_createLongArraySeed_FairLock(SeedRandomSources sources, SeedSizes sizes) {
447 final UniformRandomProvider rng = sources.getGenerator();
448 final long[] seed = new long[sizes.getSize()];
449 for (int i = 0; i < seed.length; i++) {
450 seed[i] = nextLong(FAIR_LOCK, rng);
451 }
452 return seed;
453 }
454
455
456
457
458
459
460 @Benchmark
461 public int[] Threads1_createIntArraySeedBlocks_Sync(SeedRandomSources sources, TestSizes sizes) {
462 final UniformRandomProvider rng = sources.getGenerator();
463 final int[] seed = new int[sizes.getSize()];
464 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
465 nextInt(rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
466 }
467 return seed;
468 }
469
470
471
472
473
474
475 @Benchmark
476 public long[] Threads1_createLongArraySeedBlocks_Sync(SeedRandomSources sources, TestSizes sizes) {
477 final UniformRandomProvider rng = sources.getGenerator();
478 final long[] seed = new long[sizes.getSize()];
479 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
480 nextLong(rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
481 }
482 return seed;
483 }
484
485
486
487
488
489
490 @Benchmark
491 public int[] Threads1_createIntArraySeedBlocks_UnfairLock(SeedRandomSources sources, TestSizes sizes) {
492 final UniformRandomProvider rng = sources.getGenerator();
493 final int[] seed = new int[sizes.getSize()];
494 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
495 nextInt(UNFAIR_LOCK, rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
496 }
497 return seed;
498 }
499
500
501
502
503
504
505 @Benchmark
506 public long[] Threads1_createLongArraySeedBlocks_UnfairLock(SeedRandomSources sources, TestSizes sizes) {
507 final UniformRandomProvider rng = sources.getGenerator();
508 final long[] seed = new long[sizes.getSize()];
509 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
510 nextLong(UNFAIR_LOCK, rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
511 }
512 return seed;
513 }
514
515
516
517
518
519
520 @Benchmark
521 public int[] Threads1_createIntArraySeedBlocks_FairLock(SeedRandomSources sources, TestSizes sizes) {
522 final UniformRandomProvider rng = sources.getGenerator();
523 final int[] seed = new int[sizes.getSize()];
524 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
525 nextInt(FAIR_LOCK, rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
526 }
527 return seed;
528 }
529
530
531
532
533
534
535 @Benchmark
536 public long[] Threads1_createLongArraySeedBlocks_FairLock(SeedRandomSources sources, TestSizes sizes) {
537 final UniformRandomProvider rng = sources.getGenerator();
538 final long[] seed = new long[sizes.getSize()];
539 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
540 nextLong(FAIR_LOCK, rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
541 }
542 return seed;
543 }
544
545
546
547
548
549
550 @Benchmark
551 @Threads(4)
552 public int[] Threads4_createIntArraySeed_Sync(SeedRandomSources sources, SeedSizes sizes) {
553 final UniformRandomProvider rng = sources.getGenerator();
554 final int[] seed = new int[sizes.getSize()];
555 for (int i = 0; i < seed.length; i++) {
556 seed[i] = nextInt(rng);
557 }
558 return seed;
559 }
560
561
562
563
564
565
566 @Benchmark
567 @Threads(4)
568 public long[] Threads4_createLongArraySeed_Sync(SeedRandomSources sources, SeedSizes sizes) {
569 final UniformRandomProvider rng = sources.getGenerator();
570 final long[] seed = new long[sizes.getSize()];
571 for (int i = 0; i < seed.length; i++) {
572 seed[i] = nextLong(rng);
573 }
574 return seed;
575 }
576
577
578
579
580
581
582 @Benchmark
583 @Threads(4)
584 public int[] Threads4_createIntArraySeed_UnfairLock(SeedRandomSources sources, SeedSizes sizes) {
585 final UniformRandomProvider rng = sources.getGenerator();
586 final int[] seed = new int[sizes.getSize()];
587 for (int i = 0; i < seed.length; i++) {
588 seed[i] = nextInt(UNFAIR_LOCK, rng);
589 }
590 return seed;
591 }
592
593
594
595
596
597
598 @Benchmark
599 @Threads(4)
600 public long[] Threads4_createLongArraySeed_UnfairLock(SeedRandomSources sources, SeedSizes sizes) {
601 final UniformRandomProvider rng = sources.getGenerator();
602 final long[] seed = new long[sizes.getSize()];
603 for (int i = 0; i < seed.length; i++) {
604 seed[i] = nextLong(UNFAIR_LOCK, rng);
605 }
606 return seed;
607 }
608
609
610
611
612
613
614 @Benchmark
615 @Threads(4)
616 public int[] Threads4_createIntArraySeed_FairLock(SeedRandomSources sources, SeedSizes sizes) {
617 final UniformRandomProvider rng = sources.getGenerator();
618 final int[] seed = new int[sizes.getSize()];
619 for (int i = 0; i < seed.length; i++) {
620 seed[i] = nextInt(FAIR_LOCK, rng);
621 }
622 return seed;
623 }
624
625
626
627
628
629
630 @Benchmark
631 @Threads(4)
632 public long[] Threads4_createLongArraySeed_FairLock(SeedRandomSources sources, SeedSizes sizes) {
633 final UniformRandomProvider rng = sources.getGenerator();
634 final long[] seed = new long[sizes.getSize()];
635 for (int i = 0; i < seed.length; i++) {
636 seed[i] = nextLong(FAIR_LOCK, rng);
637 }
638 return seed;
639 }
640
641
642
643
644
645
646 @Benchmark
647 @Threads(4)
648 public int[] Threads4_createIntArraySeedBlocks_Sync(SeedRandomSources sources, TestSizes sizes) {
649 final UniformRandomProvider rng = sources.getGenerator();
650 final int[] seed = new int[sizes.getSize()];
651 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
652 nextInt(rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
653 }
654 return seed;
655 }
656
657
658
659
660
661
662 @Benchmark
663 @Threads(4)
664 public long[] Threads4_createLongArraySeedBlocks_Sync(SeedRandomSources sources, TestSizes sizes) {
665 final UniformRandomProvider rng = sources.getGenerator();
666 final long[] seed = new long[sizes.getSize()];
667 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
668 nextLong(rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
669 }
670 return seed;
671 }
672
673
674
675
676
677
678 @Benchmark
679 @Threads(4)
680 public int[] Threads4_createIntArraySeedBlocks_UnfairLock(SeedRandomSources sources, TestSizes sizes) {
681 final UniformRandomProvider rng = sources.getGenerator();
682 final int[] seed = new int[sizes.getSize()];
683 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
684 nextInt(UNFAIR_LOCK, rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
685 }
686 return seed;
687 }
688
689
690
691
692
693
694 @Benchmark
695 @Threads(4)
696 public long[] Threads4_createLongArraySeedBlocks_UnfairLock(SeedRandomSources sources, TestSizes sizes) {
697 final UniformRandomProvider rng = sources.getGenerator();
698 final long[] seed = new long[sizes.getSize()];
699 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
700 nextLong(UNFAIR_LOCK, rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
701 }
702 return seed;
703 }
704
705
706
707
708
709
710 @Benchmark
711 @Threads(4)
712 public int[] Threads4_createIntArraySeedBlocks_FairLock(SeedRandomSources sources, TestSizes sizes) {
713 final UniformRandomProvider rng = sources.getGenerator();
714 final int[] seed = new int[sizes.getSize()];
715 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
716 nextInt(FAIR_LOCK, rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
717 }
718 return seed;
719 }
720
721
722
723
724
725
726 @Benchmark
727 @Threads(4)
728 public long[] Threads4_createLongArraySeedBlocks_FairLock(SeedRandomSources sources, TestSizes sizes) {
729 final UniformRandomProvider rng = sources.getGenerator();
730 final long[] seed = new long[sizes.getSize()];
731 for (int i = 0; i < seed.length; i += sizes.getBlockSize()) {
732 nextLong(FAIR_LOCK, rng, seed, i, Math.min(i + sizes.getBlockSize(), seed.length));
733 }
734 return seed;
735 }
736 }