View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.rng.examples.jmh.simple;
19  
20  import org.openjdk.jmh.annotations.Benchmark;
21  import org.openjdk.jmh.annotations.BenchmarkMode;
22  import org.openjdk.jmh.annotations.Fork;
23  import org.openjdk.jmh.annotations.Level;
24  import org.openjdk.jmh.annotations.Measurement;
25  import org.openjdk.jmh.annotations.Mode;
26  import org.openjdk.jmh.annotations.OutputTimeUnit;
27  import org.openjdk.jmh.annotations.Param;
28  import org.openjdk.jmh.annotations.Scope;
29  import org.openjdk.jmh.annotations.Setup;
30  import org.openjdk.jmh.annotations.State;
31  import org.openjdk.jmh.annotations.Warmup;
32  import org.openjdk.jmh.infra.Blackhole;
33  
34  import java.lang.reflect.Constructor;
35  import java.lang.reflect.InvocationTargetException;
36  import java.util.Arrays;
37  import java.util.concurrent.TimeUnit;
38  
39  import org.apache.commons.rng.UniformRandomProvider;
40  import org.apache.commons.rng.core.source32.ISAACRandom;
41  import org.apache.commons.rng.core.source32.JDKRandom;
42  import org.apache.commons.rng.core.source32.KISSRandom;
43  import org.apache.commons.rng.core.source32.MersenneTwister;
44  import org.apache.commons.rng.core.source32.MultiplyWithCarry256;
45  import org.apache.commons.rng.core.source32.Well1024a;
46  import org.apache.commons.rng.core.source32.Well19937a;
47  import org.apache.commons.rng.core.source32.Well19937c;
48  import org.apache.commons.rng.core.source32.Well44497a;
49  import org.apache.commons.rng.core.source32.Well44497b;
50  import org.apache.commons.rng.core.source32.Well512a;
51  import org.apache.commons.rng.core.source32.XoRoShiRo64Star;
52  import org.apache.commons.rng.core.source32.XoRoShiRo64StarStar;
53  import org.apache.commons.rng.core.source32.XoShiRo128Plus;
54  import org.apache.commons.rng.core.source32.XoShiRo128StarStar;
55  import org.apache.commons.rng.core.source64.MersenneTwister64;
56  import org.apache.commons.rng.core.source64.SplitMix64;
57  import org.apache.commons.rng.core.source64.TwoCmres;
58  import org.apache.commons.rng.core.source64.XoRoShiRo128Plus;
59  import org.apache.commons.rng.core.source64.XoRoShiRo128StarStar;
60  import org.apache.commons.rng.core.source64.XoShiRo256Plus;
61  import org.apache.commons.rng.core.source64.XoShiRo256StarStar;
62  import org.apache.commons.rng.core.source64.XoShiRo512Plus;
63  import org.apache.commons.rng.core.source64.XoShiRo512StarStar;
64  import org.apache.commons.rng.core.source64.XorShift1024Star;
65  import org.apache.commons.rng.core.source64.XorShift1024StarPhi;
66  import org.apache.commons.rng.core.util.NumberFactory;
67  import org.apache.commons.rng.examples.jmh.RandomSourceValues;
68  import org.apache.commons.rng.simple.RandomSource;
69  import org.apache.commons.rng.simple.internal.ProviderBuilder.RandomSourceInternal;
70  import org.apache.commons.rng.simple.internal.SeedFactory;
71  
72  /**
73   * Executes a benchmark to compare the speed of construction of random number providers.
74   *
75   * <p>Note that random number providers are created and then used. Thus the construction time must
76   * be analysed together with the run time performance benchmark (see for example
77   * {@link org.apache.commons.rng.examples.jmh.core.NextLongGenerationPerformance
78   * NextIntGenerationPerformance} and
79   * {@link org.apache.commons.rng.examples.jmh.core.NextLongGenerationPerformance
80   * NextLongGenerationPerformance}).
81   *
82   * <pre>
83   * [Total time] = [Construction time] + [Run time]
84   * </pre>
85   *
86   * <p>Selection of a suitable random number provider based on construction speed should consider
87   * when the construction time is a large fraction of the run time. In the majority of cases the
88   * run time will be the largest component of the total time and the provider should be selected
89   * based on its other properties such as the period, statistical randomness and speed.
90   */
91  @BenchmarkMode(Mode.AverageTime)
92  @OutputTimeUnit(TimeUnit.MICROSECONDS)
93  @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
94  @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
95  @State(Scope.Benchmark)
96  @Fork(value = 1, jvmArgs = { "-server", "-Xms512M", "-Xmx512M" })
97  public class ConstructionPerformance {
98  
99      /** The number of different constructor seeds. */
100     private static final int SEEDS = 500;
101     /**
102      * The maximum seed array size. This is irrespective of data type just to ensure
103      * there is enough data in the random seeds. The value is for WELL_44497_A.
104      */
105     private static final int MAX_SEED_SIZE = 1391;
106     /** The {@link Long} seeds. */
107     private static final Long[] LONG_SEEDS;
108     /** The {@link Integer} seeds. */
109     private static final Integer[] INTEGER_SEEDS;
110     /** The {@code long[]} seeds. */
111     private static final long[][] LONG_ARRAY_SEEDS;
112     /** The {@code int[]} seeds. */
113     private static final int[][] INT_ARRAY_SEEDS;
114     /** The {@code byte[]} seeds. */
115     private static final byte[][] BYTE_ARRAY_SEEDS;
116 
117     /**
118      * The values. Must NOT be final to prevent JVM optimisation!
119      * This is used to test the speed of the BlackHole consuming an object.
120      */
121     private Object[] values;
122 
123     static {
124         LONG_SEEDS = new Long[SEEDS];
125         INTEGER_SEEDS = new Integer[SEEDS];
126         LONG_ARRAY_SEEDS = new long[SEEDS][];
127         INT_ARRAY_SEEDS = new int[SEEDS][];
128         BYTE_ARRAY_SEEDS = new byte[SEEDS][];
129         final UniformRandomProvider rng = RandomSource.XOR_SHIFT_1024_S_PHI.create();
130         for (int i = 0; i < SEEDS; i++) {
131             final long[] longArray = new long[MAX_SEED_SIZE];
132             final int[] intArray = new int[MAX_SEED_SIZE];
133             for (int j = 0; j < MAX_SEED_SIZE; j++) {
134                 longArray[j] = rng.nextLong();
135                 intArray[j] = (int) longArray[j];
136             }
137             LONG_SEEDS[i] = longArray[0];
138             INTEGER_SEEDS[i] = intArray[0];
139             LONG_ARRAY_SEEDS[i] = longArray;
140             INT_ARRAY_SEEDS[i] = intArray;
141             BYTE_ARRAY_SEEDS[i] = NumberFactory.makeByteArray(longArray);
142         }
143     }
144 
145     /**
146      * Default constructor to initialize state.
147      */
148     public ConstructionPerformance() {
149         values = new Object[SEEDS];
150         for (int i = 0; i < SEEDS; i++) {
151             values[i] = new Object();
152         }
153     }
154 
155     /**
156      * The benchmark state (retrieve the various "RandomSource"s).
157      */
158     @State(Scope.Benchmark)
159     public static class Sources extends RandomSourceValues {
160         /** The native seeds. */
161         private Object[] nativeSeeds;
162 
163         /** The native seeds with arrays truncated to 1 element. */
164         private Object[] nativeSeeds1;
165 
166         /** The {@code byte[]} seeds, truncated to the appropriate length for the native seed type. */
167         private byte[][] byteSeeds;
168 
169         /** The implementing class for the random source. */
170         private Class<?> implementingClass;
171 
172         /** The constructor. */
173         private Constructor<Object> constructor;
174 
175         /**
176          * Gets the native seeds for the RandomSource.
177          *
178          * @return the native seeds
179          */
180         public Object[] getNativeSeeds() {
181             return nativeSeeds;
182         }
183 
184         /**
185          * Gets the native seeds for the RandomSource with arrays truncated to length 1.
186          *
187          * @return the native seeds
188          */
189         public Object[] getNativeSeeds1() {
190             return nativeSeeds1;
191         }
192 
193         /**
194          * Gets the native seeds for the RandomSource.
195          *
196          * @return the native seeds
197          */
198         public byte[][] getByteSeeds() {
199             return byteSeeds;
200         }
201 
202         /**
203          * Gets the implementing class.
204          *
205          * @return the implementing class
206          */
207         public Class<?> getImplementingClass() {
208             return implementingClass;
209         }
210 
211         /**
212          * Gets the constructor.
213          *
214          * @return the constructor
215          */
216         public Constructor<Object> getConstructor() {
217             return constructor;
218         }
219 
220         /**
221          * Create the random source and the test seeds.
222          */
223         @Override
224         @SuppressWarnings("unchecked")
225         @Setup(Level.Trial)
226         public void setup() {
227             super.setup();
228             final RandomSource randomSource = getRandomSource();
229             nativeSeeds = findNativeSeeds(randomSource);
230 
231             // Truncate array seeds to length 1
232             if (nativeSeeds[0].getClass().isArray()) {
233                 nativeSeeds1 = new Object[SEEDS];
234                 for (int i = 0; i < SEEDS; i++) {
235                     nativeSeeds1[i] = copy(nativeSeeds[i], 1);
236                 }
237             } else {
238                 // N/A
239                 nativeSeeds1 = nativeSeeds;
240             }
241 
242             // Convert seeds to bytes
243             byteSeeds = new byte[SEEDS][];
244             final int byteSize = findNativeSeedLength(randomSource) *
245                            findNativeSeedElementByteSize(randomSource);
246             for (int i = 0; i < SEEDS; i++) {
247                 byteSeeds[i] = Arrays.copyOf(BYTE_ARRAY_SEEDS[i], byteSize);
248             }
249 
250             // Cache the class type and constructor
251             implementingClass = getRandomSourceInternal(randomSource).getRng();
252             try {
253                 constructor = (Constructor<Object>) implementingClass.getConstructor(nativeSeeds[0].getClass());
254             } catch (NoSuchMethodException ex) {
255                 throw new IllegalStateException("Failed to find the constructor", ex);
256             }
257         }
258 
259         /**
260          * Copy the specified length of the provided array object.
261          *
262          * @param object the object
263          * @param length the length
264          * @return the copy
265          */
266         private static Object copy(Object object, int length) {
267             if (object instanceof int[]) {
268                 return Arrays.copyOf((int[]) object, length);
269             }
270             if (object instanceof long[]) {
271                 return Arrays.copyOf((long[]) object, length);
272             }
273             throw new AssertionError("Unknown seed array");
274         }
275 
276         /**
277          * Find the native seeds for the RandomSource.
278          *
279          * @param randomSource the random source
280          * @return the native seeds
281          */
282         private static Object[] findNativeSeeds(RandomSource randomSource) {
283             switch (randomSource) {
284             case TWO_CMRES:
285             case TWO_CMRES_SELECT:
286                 return INTEGER_SEEDS;
287             case JDK:
288             case SPLIT_MIX_64:
289                 return LONG_SEEDS;
290             case WELL_512_A:
291             case WELL_1024_A:
292             case WELL_19937_A:
293             case WELL_19937_C:
294             case WELL_44497_A:
295             case WELL_44497_B:
296             case MT:
297             case ISAAC:
298             case MWC_256:
299             case KISS:
300             case XO_RO_SHI_RO_64_S:
301             case XO_RO_SHI_RO_64_SS:
302             case XO_SHI_RO_128_PLUS:
303             case XO_SHI_RO_128_SS:
304                 return INT_ARRAY_SEEDS;
305             case XOR_SHIFT_1024_S:
306             case XOR_SHIFT_1024_S_PHI:
307             case MT_64:
308             case XO_RO_SHI_RO_128_PLUS:
309             case XO_RO_SHI_RO_128_SS:
310             case XO_SHI_RO_256_PLUS:
311             case XO_SHI_RO_256_SS:
312             case XO_SHI_RO_512_PLUS:
313             case XO_SHI_RO_512_SS:
314                 return LONG_ARRAY_SEEDS;
315             default:
316                 throw new AssertionError("Unknown native seed");
317             }
318         }
319 
320         /**
321          * Find the length of the native seed (number of elements).
322          *
323          * @param randomSource the random source
324          * @return the seed length
325          */
326         private static int findNativeSeedLength(RandomSource randomSource) {
327             switch (randomSource) {
328             case JDK:
329             case SPLIT_MIX_64:
330             case TWO_CMRES:
331             case TWO_CMRES_SELECT:
332                 return 1;
333             case WELL_512_A:
334                 return 16;
335             case WELL_1024_A:
336                 return 32;
337             case WELL_19937_A:
338             case WELL_19937_C:
339                 return 624;
340             case WELL_44497_A:
341             case WELL_44497_B:
342                 return 1391;
343             case MT:
344                 return 624;
345             case ISAAC:
346                 return 256;
347             case XOR_SHIFT_1024_S:
348             case XOR_SHIFT_1024_S_PHI:
349                 return 16;
350             case MT_64:
351                 return 312;
352             case MWC_256:
353                 return 257;
354             case KISS:
355                 return 4;
356             case XO_RO_SHI_RO_64_S:
357             case XO_RO_SHI_RO_64_SS:
358                 return 2;
359             case XO_SHI_RO_128_PLUS:
360             case XO_SHI_RO_128_SS:
361                 return 4;
362             case XO_RO_SHI_RO_128_PLUS:
363             case XO_RO_SHI_RO_128_SS:
364                 return 2;
365             case XO_SHI_RO_256_PLUS:
366             case XO_SHI_RO_256_SS:
367                 return 4;
368             case XO_SHI_RO_512_PLUS:
369             case XO_SHI_RO_512_SS:
370                 return 8;
371             default:
372                 throw new AssertionError("Unknown native seed size");
373             }
374         }
375 
376         /**
377          * Find the byte size of a single element of the native seed.
378          *
379          * @param randomSource the random source
380          * @return the seed element byte size
381          */
382         private static int findNativeSeedElementByteSize(RandomSource randomSource) {
383             switch (randomSource) {
384             case JDK:
385             case WELL_512_A:
386             case WELL_1024_A:
387             case WELL_19937_A:
388             case WELL_19937_C:
389             case WELL_44497_A:
390             case WELL_44497_B:
391             case MT:
392             case ISAAC:
393             case TWO_CMRES:
394             case TWO_CMRES_SELECT:
395             case MWC_256:
396             case KISS:
397             case XO_RO_SHI_RO_64_S:
398             case XO_RO_SHI_RO_64_SS:
399             case XO_SHI_RO_128_PLUS:
400             case XO_SHI_RO_128_SS:
401                 return 4; // int
402             case SPLIT_MIX_64:
403             case XOR_SHIFT_1024_S:
404             case XOR_SHIFT_1024_S_PHI:
405             case MT_64:
406             case XO_RO_SHI_RO_128_PLUS:
407             case XO_RO_SHI_RO_128_SS:
408             case XO_SHI_RO_256_PLUS:
409             case XO_SHI_RO_256_SS:
410             case XO_SHI_RO_512_PLUS:
411             case XO_SHI_RO_512_SS:
412                 return 8; // long
413             default:
414                 throw new AssertionError("Unknown native seed element byte size");
415             }
416         }
417 
418         /**
419          * Gets the random source internal.
420          *
421          * @param randomSource the random source
422          * @return the random source internal
423          */
424         private static RandomSourceInternal getRandomSourceInternal(RandomSource randomSource) {
425             switch (randomSource) {
426             case JDK: return RandomSourceInternal.JDK;
427             case WELL_512_A: return RandomSourceInternal.WELL_512_A;
428             case WELL_1024_A: return RandomSourceInternal.WELL_1024_A;
429             case WELL_19937_A: return RandomSourceInternal.WELL_19937_A;
430             case WELL_19937_C: return RandomSourceInternal.WELL_19937_C;
431             case WELL_44497_A: return RandomSourceInternal.WELL_44497_A;
432             case WELL_44497_B: return RandomSourceInternal.WELL_44497_B;
433             case MT: return RandomSourceInternal.MT;
434             case ISAAC: return RandomSourceInternal.ISAAC;
435             case TWO_CMRES: return RandomSourceInternal.TWO_CMRES;
436             case TWO_CMRES_SELECT: return RandomSourceInternal.TWO_CMRES_SELECT;
437             case MWC_256: return RandomSourceInternal.MWC_256;
438             case KISS: return RandomSourceInternal.KISS;
439             case SPLIT_MIX_64: return RandomSourceInternal.SPLIT_MIX_64;
440             case XOR_SHIFT_1024_S: return RandomSourceInternal.XOR_SHIFT_1024_S;
441             case MT_64: return RandomSourceInternal.MT_64;
442             case XOR_SHIFT_1024_S_PHI: return RandomSourceInternal.XOR_SHIFT_1024_S_PHI;
443             case XO_RO_SHI_RO_64_S: return RandomSourceInternal.XO_RO_SHI_RO_64_S;
444             case XO_RO_SHI_RO_64_SS: return RandomSourceInternal.XO_RO_SHI_RO_64_SS;
445             case XO_SHI_RO_128_PLUS: return RandomSourceInternal.XO_SHI_RO_128_PLUS;
446             case XO_SHI_RO_128_SS: return RandomSourceInternal.XO_SHI_RO_128_SS;
447             case XO_RO_SHI_RO_128_PLUS: return RandomSourceInternal.XO_RO_SHI_RO_128_PLUS;
448             case XO_RO_SHI_RO_128_SS: return RandomSourceInternal.XO_RO_SHI_RO_128_SS;
449             case XO_SHI_RO_256_PLUS: return RandomSourceInternal.XO_SHI_RO_256_PLUS;
450             case XO_SHI_RO_256_SS: return RandomSourceInternal.XO_SHI_RO_256_SS;
451             case XO_SHI_RO_512_PLUS: return RandomSourceInternal.XO_SHI_RO_512_PLUS;
452             case XO_SHI_RO_512_SS: return RandomSourceInternal.XO_SHI_RO_512_SS;
453             default:
454                 throw new AssertionError("Unknown random source internal");
455             }
456         }
457     }
458 
459     /**
460      * The number of {@code int} values that are required to seed a generator.
461      */
462     @State(Scope.Benchmark)
463     public static class IntSizes {
464         /** The number of values. */
465         @Param({"2",
466                 "4",
467                 "32",
468                 "128", // Legacy limit on array size generation
469                 "256",
470                 "257",
471                 "624",
472                 "1391",
473             })
474         private int size;
475 
476         /**
477          * Gets the number of {@code int} values required.
478          *
479          * @return the size
480          */
481         public int getSize() {
482             return size;
483         }
484     }
485 
486     /**
487      * The number of {@code long} values that are required to seed a generator.
488      */
489     @State(Scope.Benchmark)
490     public static class LongSizes {
491         /** The number of values. */
492         @Param({"2",
493                 "4",
494                 "8",
495                 "16",
496                 "128", // Legacy limit on array size generation
497                 "312",
498             })
499         private int size;
500 
501         /**
502          * Gets the number of {@code long} values required.
503          *
504          * @return the size
505          */
506         public int getSize() {
507             return size;
508         }
509     }
510 
511     /**
512      * Baseline for JMH consuming a number of constructed objects.
513      * This shows the JMH timing overhead for all the construction benchmarks.
514      *
515      * @param bh Data sink.
516      */
517     @Benchmark
518     public void baselineConsumeObject(Blackhole bh) {
519         for (int i = 0; i < SEEDS; i++) {
520             bh.consume(values[i]);
521         }
522     }
523 
524     /**
525      * Baseline for JMH consuming a number of new objects.
526      *
527      * @param bh Data sink.
528      */
529     @Benchmark
530     public void newObject(Blackhole bh) {
531         for (int i = 0; i < SEEDS; i++) {
532             bh.consume(new Object());
533         }
534     }
535 
536     /**
537      * @param bh Data sink.
538      */
539     @Benchmark
540     public void newJDKRandom(Blackhole bh) {
541         for (int i = 0; i < SEEDS; i++) {
542             bh.consume(new JDKRandom(LONG_SEEDS[i]));
543         }
544     }
545 
546     /**
547      * @param bh Data sink.
548      */
549     @Benchmark
550     public void newWell512a(Blackhole bh) {
551         for (int i = 0; i < SEEDS; i++) {
552             bh.consume(new Well512a(INT_ARRAY_SEEDS[i]));
553         }
554     }
555 
556     /**
557      * @param bh Data sink.
558      */
559     @Benchmark
560     public void newWell1024a(Blackhole bh) {
561         for (int i = 0; i < SEEDS; i++) {
562             bh.consume(new Well1024a(INT_ARRAY_SEEDS[i]));
563         }
564     }
565 
566     /**
567      * @param bh Data sink.
568      */
569     @Benchmark
570     public void newWell19937a(Blackhole bh) {
571         for (int i = 0; i < SEEDS; i++) {
572             bh.consume(new Well19937a(INT_ARRAY_SEEDS[i]));
573         }
574     }
575 
576     /**
577      * @param bh Data sink.
578      */
579     @Benchmark
580     public void newWell19937c(Blackhole bh) {
581         for (int i = 0; i < SEEDS; i++) {
582             bh.consume(new Well19937c(INT_ARRAY_SEEDS[i]));
583         }
584     }
585 
586     /**
587      * @param bh Data sink.
588      */
589     @Benchmark
590     public void newWell44497a(Blackhole bh) {
591         for (int i = 0; i < SEEDS; i++) {
592             bh.consume(new Well44497a(INT_ARRAY_SEEDS[i]));
593         }
594     }
595 
596     /**
597      * @param bh Data sink.
598      */
599     @Benchmark
600     public void newWell44497b(Blackhole bh) {
601         for (int i = 0; i < SEEDS; i++) {
602             bh.consume(new Well44497b(INT_ARRAY_SEEDS[i]));
603         }
604     }
605 
606     /**
607      * @param bh Data sink.
608      */
609     @Benchmark
610     public void newMersenneTwister(Blackhole bh) {
611         for (int i = 0; i < SEEDS; i++) {
612             bh.consume(new MersenneTwister(INT_ARRAY_SEEDS[i]));
613         }
614     }
615 
616     /**
617      * @param bh Data sink.
618      */
619     @Benchmark
620     public void newISAACRandom(Blackhole bh) {
621         for (int i = 0; i < SEEDS; i++) {
622             bh.consume(new ISAACRandom(INT_ARRAY_SEEDS[i]));
623         }
624     }
625 
626     /**
627      * @param bh Data sink.
628      */
629     @Benchmark
630     public void newSplitMix64(Blackhole bh) {
631         for (int i = 0; i < SEEDS; i++) {
632             bh.consume(new SplitMix64(LONG_SEEDS[i]));
633         }
634     }
635 
636     /**
637      * @param bh Data sink.
638      */
639     @Benchmark
640     public void newXorShift1024Star(Blackhole bh) {
641         for (int i = 0; i < SEEDS; i++) {
642             bh.consume(new XorShift1024Star(LONG_ARRAY_SEEDS[i]));
643         }
644     }
645 
646     /**
647      * @param bh Data sink.
648      */
649     @Benchmark
650     public void newTwoCmres(Blackhole bh) {
651         for (int i = 0; i < SEEDS; i++) {
652             bh.consume(new TwoCmres(INTEGER_SEEDS[i]));
653         }
654     }
655 
656     /**
657      * @param bh Data sink.
658      */
659     @Benchmark
660     public void newMersenneTwister64(Blackhole bh) {
661         for (int i = 0; i < SEEDS; i++) {
662             bh.consume(new MersenneTwister64(LONG_ARRAY_SEEDS[i]));
663         }
664     }
665 
666     /**
667      * @param bh Data sink.
668      */
669     @Benchmark
670     public void newMultiplyWithCarry256(Blackhole bh) {
671         for (int i = 0; i < SEEDS; i++) {
672             bh.consume(new MultiplyWithCarry256(INT_ARRAY_SEEDS[i]));
673         }
674     }
675 
676     /**
677      * @param bh Data sink.
678      */
679     @Benchmark
680     public void newKISSRandom(Blackhole bh) {
681         for (int i = 0; i < SEEDS; i++) {
682             bh.consume(new KISSRandom(INT_ARRAY_SEEDS[i]));
683         }
684     }
685 
686     /**
687      * @param bh Data sink.
688      */
689     @Benchmark
690     public void newXorShift1024StarPhi(Blackhole bh) {
691         for (int i = 0; i < SEEDS; i++) {
692             bh.consume(new XorShift1024StarPhi(LONG_ARRAY_SEEDS[i]));
693         }
694     }
695 
696     /**
697      * @param bh Data sink.
698      */
699     @Benchmark
700     public void newXoRoShiRo64Star(Blackhole bh) {
701         for (int i = 0; i < SEEDS; i++) {
702             bh.consume(new XoRoShiRo64Star(INT_ARRAY_SEEDS[i]));
703         }
704     }
705 
706     /**
707      * @param bh Data sink.
708      */
709     @Benchmark
710     public void newXoRoShiRo64StarStar(Blackhole bh) {
711         for (int i = 0; i < SEEDS; i++) {
712             bh.consume(new XoRoShiRo64StarStar(INT_ARRAY_SEEDS[i]));
713         }
714     }
715 
716     /**
717      * @param bh Data sink.
718      */
719     @Benchmark
720     public void newXoShiRo128Plus(Blackhole bh) {
721         for (int i = 0; i < SEEDS; i++) {
722             bh.consume(new XoShiRo128Plus(INT_ARRAY_SEEDS[i]));
723         }
724     }
725 
726     /**
727      * @param bh Data sink.
728      */
729     @Benchmark
730     public void newXoShiRo128StarStar(Blackhole bh) {
731         for (int i = 0; i < SEEDS; i++) {
732             bh.consume(new XoShiRo128StarStar(INT_ARRAY_SEEDS[i]));
733         }
734     }
735 
736     /**
737      * @param bh Data sink.
738      */
739     @Benchmark
740     public void newXoRoShiRo128Plus(Blackhole bh) {
741         for (int i = 0; i < SEEDS; i++) {
742             bh.consume(new XoRoShiRo128Plus(LONG_ARRAY_SEEDS[i]));
743         }
744     }
745 
746     /**
747      * @param bh Data sink.
748      */
749     @Benchmark
750     public void newXoRoShiRo128StarStar(Blackhole bh) {
751         for (int i = 0; i < SEEDS; i++) {
752             bh.consume(new XoRoShiRo128StarStar(LONG_ARRAY_SEEDS[i]));
753         }
754     }
755 
756     /**
757      * @param bh Data sink.
758      */
759     @Benchmark
760     public void newXoShiRo256Plus(Blackhole bh) {
761         for (int i = 0; i < SEEDS; i++) {
762             bh.consume(new XoShiRo256Plus(LONG_ARRAY_SEEDS[i]));
763         }
764     }
765 
766     /**
767      * @param bh Data sink.
768      */
769     @Benchmark
770     public void newXoShiRo256StarStar(Blackhole bh) {
771         for (int i = 0; i < SEEDS; i++) {
772             bh.consume(new XoShiRo256StarStar(LONG_ARRAY_SEEDS[i]));
773         }
774     }
775 
776     /**
777      * @param bh Data sink.
778      */
779     @Benchmark
780     public void newXoShiRo512Plus(Blackhole bh) {
781         for (int i = 0; i < SEEDS; i++) {
782             bh.consume(new XoShiRo512Plus(LONG_ARRAY_SEEDS[i]));
783         }
784     }
785 
786     /**
787      * @param bh Data sink.
788      */
789     @Benchmark
790     public void newXoShiRo512StarStar(Blackhole bh) {
791         for (int i = 0; i < SEEDS; i++) {
792             bh.consume(new XoShiRo512StarStar(LONG_ARRAY_SEEDS[i]));
793         }
794     }
795 
796     /**
797      * Create a new instance using reflection with a cached constructor.
798      *
799      * @param sources Source of randomness.
800      * @param bh      Data sink.
801      * @throws InvocationTargetException If reflection failed.
802      * @throws IllegalAccessException If reflection failed.
803      * @throws InstantiationException If reflection failed.
804      */
805     @Benchmark
806     public void newInstance(Sources sources, Blackhole bh) throws InstantiationException,
807             IllegalAccessException, InvocationTargetException {
808         final Object[] nativeSeeds = sources.getNativeSeeds();
809         final Constructor<?> constructor = sources.getConstructor();
810         for (int i = 0; i < SEEDS; i++) {
811             bh.consume(constructor.newInstance(nativeSeeds[i]));
812         }
813     }
814 
815     /**
816      * Create a new instance using reflection to lookup the constructor then invoke it.
817      *
818      * @param sources Source of randomness.
819      * @param bh      Data sink.
820      * @throws InvocationTargetException If reflection failed.
821      * @throws IllegalAccessException If reflection failed.
822      * @throws InstantiationException If reflection failed.
823      * @throws SecurityException If reflection failed.
824      * @throws NoSuchMethodException If reflection failed.
825      * @throws IllegalArgumentException If reflection failed.
826      */
827     @Benchmark
828     public void lookupNewInstance(Sources sources, Blackhole bh) throws InstantiationException,
829             IllegalAccessException, InvocationTargetException, NoSuchMethodException {
830         final Object[] nativeSeeds = sources.getNativeSeeds();
831         final Class<?> implementingClass = sources.getImplementingClass();
832         for (int i = 0; i < SEEDS; i++) {
833             bh.consume(implementingClass.getConstructor(nativeSeeds[i].getClass()).newInstance(nativeSeeds[i]));
834         }
835     }
836 
837     /**
838      * @param sources Source of randomness.
839      * @param bh      Data sink.
840      */
841     @Benchmark
842     public void createNullSeed(Sources sources, Blackhole bh) {
843         final RandomSource randomSource = sources.getRandomSource();
844         final Object seed = null;
845         for (int i = 0; i < SEEDS; i++) {
846             bh.consume(randomSource.create(seed));
847         }
848     }
849 
850     /**
851      * @param sources Source of randomness.
852      * @param bh      Data sink.
853      */
854     @Benchmark
855     public void createNativeSeed(Sources sources, Blackhole bh) {
856         final RandomSource randomSource = sources.getRandomSource();
857         final Object[] nativeSeeds = sources.getNativeSeeds();
858         for (int i = 0; i < SEEDS; i++) {
859             bh.consume(randomSource.create(nativeSeeds[i]));
860         }
861     }
862 
863     /**
864      * Test the native seed with arrays truncated to length 1. This tests the speed
865      * of self-seeding.
866      *
867      * <p>This test is the same as {@link #createNativeSeed(Sources, Blackhole)} if
868      * the random source native seed is not an array.
869      *
870      * @param sources Source of randomness.
871      * @param bh      Data sink.
872      */
873     @Benchmark
874     public void createSelfSeed(Sources sources, Blackhole bh) {
875         final RandomSource randomSource = sources.getRandomSource();
876         final Object[] nativeSeeds1 = sources.getNativeSeeds1();
877         for (int i = 0; i < SEEDS; i++) {
878             bh.consume(randomSource.create(nativeSeeds1[i]));
879         }
880     }
881 
882     /**
883      * @param sources Source of randomness.
884      * @param bh      Data sink.
885      */
886     @Benchmark
887     public void createLongSeed(Sources sources, Blackhole bh) {
888         final RandomSource randomSource = sources.getRandomSource();
889         for (int i = 0; i < SEEDS; i++) {
890             bh.consume(randomSource.create(LONG_SEEDS[i]));
891         }
892     }
893 
894     /**
895      * @param sources Source of randomness.
896      * @param bh      Data sink.
897      */
898     @Benchmark
899     public void createByteArray(Sources sources, Blackhole bh) {
900         final RandomSource randomSource = sources.getRandomSource();
901         final byte[][] byteSeeds = sources.getByteSeeds();
902         for (int i = 0; i < SEEDS; i++) {
903             bh.consume(randomSource.create(byteSeeds[i]));
904         }
905     }
906 
907     /**
908      * @param sizes   Size of {@code int[]} seed.
909      * @param bh      Data sink.
910      */
911     @Benchmark
912     public void createIntArraySeed(IntSizes sizes, Blackhole bh) {
913         for (int i = 0; i < SEEDS; i++) {
914             bh.consume(SeedFactory.createIntArray(sizes.getSize()));
915         }
916     }
917 
918     /**
919      * @param sizes   Size of {@code long[]} seed.
920      * @param bh      Data sink.
921      */
922     @Benchmark
923     public void createLongArraySeed(LongSizes sizes, Blackhole bh) {
924         for (int i = 0; i < SEEDS; i++) {
925             bh.consume(SeedFactory.createLongArray(sizes.getSize()));
926         }
927     }
928 
929     /**
930      * @param bh      Data sink.
931      */
932     @Benchmark
933     public void createSingleIntegerSeed(Blackhole bh) {
934         for (int i = 0; i < SEEDS; i++) {
935             // This has to be boxed to an object
936             bh.consume(Integer.valueOf(SeedFactory.createInt()));
937         }
938     }
939 
940     /**
941      * @param bh      Data sink.
942      */
943     @Benchmark
944     public void createSingleLongSeed(Blackhole bh) {
945         for (int i = 0; i < SEEDS; i++) {
946             // This has to be boxed to an object
947             bh.consume(Long.valueOf(SeedFactory.createLong()));
948         }
949     }
950 }