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.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   * Executes a benchmark to compare the speed of generating an array of {@code int/long} values
41   * in a thread-safe way.
42   *
43   * <p>Uses an upper limit of 128 for the size of an array seed.</p>
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       * The lock to own when using the generator. This lock is unfair and there is no
54       * particular access order for waiting threads.
55       *
56       * <p>This is used as an alternative to {@code synchronized} statements.</p>
57       */
58      private static final ReentrantLock UNFAIR_LOCK = new ReentrantLock(false);
59  
60      /**
61       * The lock to own when using the generator. This lock is fair and the longest waiting
62       * thread will be favoured.
63       *
64       * <p>This is used as an alternative to {@code synchronized} statements.</p>
65       */
66      private static final ReentrantLock FAIR_LOCK = new ReentrantLock(true);
67  
68      /** The int[] value. Must NOT be final to prevent JVM optimisation! */
69      private int[] intValue;
70  
71      /** The long[] value. Must NOT be final to prevent JVM optimisation! */
72      private long[] longValue;
73  
74      /**
75       * The RandomSource to test.
76       */
77      @State(Scope.Benchmark)
78      public static class SeedRandomSources {
79          /**
80           * RNG providers to test.
81           * For seed generation only long period generators should be considered.
82           */
83          @Param({"WELL_44497_B",
84                  "XOR_SHIFT_1024_S_PHI",
85                  })
86          private String randomSourceName;
87  
88          /** RNG. */
89          private UniformRandomProvider generator;
90  
91          /**
92           * Gets the generator.
93           *
94           * @return the RNG.
95           */
96          public UniformRandomProvider getGenerator() {
97              return generator;
98          }
99  
100         /**
101          * Look-up the {@link RandomSource} from the name and instantiates the generator.
102          */
103         @Setup
104         public void setup() {
105             generator = RandomSource.create(RandomSource.valueOf(randomSourceName));
106         }
107     }
108 
109     /**
110      * The number of values that are required to seed a generator.
111      */
112     @State(Scope.Benchmark)
113     public static class SeedSizes {
114         /** The number of values. */
115         @Param({"2", "4", "8", "16", "32", "64", "128"})
116         private int size;
117 
118         /**
119          * Gets the number of {@code int} values required.
120          *
121          * @return the size
122          */
123         public int getSize() {
124             return size;
125         }
126     }
127 
128     /**
129      * Define the number of seed values to create and the number to compute per synchronisation on
130      * the generator.
131      */
132     @State(Scope.Benchmark)
133     public static class TestSizes {
134         /** The number of values. */
135         @Param({"2", "4", "8", "16", "32", "64", "128"})
136         private int size;
137 
138         /** The block size is the number of values to compute per synchronisation on the generator. */
139         @Param({"2", "4", "8", "16", "32", "64", "128"})
140         private int blockSize;
141 
142         /**
143          * Gets the number of {@code int} values required.
144          *
145          * @return the size
146          */
147         public int getSize() {
148             return size;
149         }
150 
151         /**
152          * @return the block size
153          */
154         public int getBlockSize() {
155             return blockSize;
156         }
157 
158         /**
159          * Verify the size parameters. This throws an exception if the block size exceeds the seed
160          * size as the test is redundant. JMH will catch the exception and run the next benchmark.
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      * Get the next {@code int} from the RNG. This is synchronized on the generator.
172      *
173      * @param rng Random generator.
174      * @return the int
175      */
176     private static int nextInt(UniformRandomProvider rng) {
177         synchronized (rng) {
178             return rng.nextInt();
179         }
180     }
181 
182     /**
183      * Get the next {@code long} from the RNG. This is synchronized on the generator.
184      *
185      * @param rng Random generator.
186      * @return the long
187      */
188     private static long nextLong(UniformRandomProvider rng) {
189         synchronized (rng) {
190             return rng.nextLong();
191         }
192     }
193 
194     /**
195      * Fill the array between {@code start} inclusive and {@code end} exclusive from the RNG.
196      * This is synchronized on the generator.
197      *
198      * @param rng Random generator.
199      * @param array Array data.
200      * @param start Start (inclusive).
201      * @param end End (exclusive).
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      * Fill the array between {@code start} inclusive and {@code end} exclusive from the
213      * RNG. This is synchronized on the generator.
214      *
215      * @param rng Random generator.
216      * @param array Array data.
217      * @param start Start (inclusive).
218      * @param end End (exclusive).
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      * Get the next {@code int} from the RNG. The lock is used to guard access to the generator.
230      *
231      * @param lock Lock guarding access to the generator.
232      * @param rng Random generator.
233      * @return the int
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      * Get the next {@code long} from the RNG. The lock is used to guard access to the generator.
246      *
247      * @param lock Lock guarding access to the generator.
248      * @param rng Random generator.
249      * @return the long
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      * Fill the array between {@code start} inclusive and {@code end} exclusive from the RNG.
262      * The lock is used to guard access to the generator.
263      *
264      * @param lock Lock guarding access to the generator.
265      * @param rng Random generator.
266      * @param array Array data.
267      * @param start Start (inclusive).
268      * @param end End (exclusive).
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      * Fill the array between {@code start} inclusive and {@code end} exclusive from the RNG.
283      * The lock is used to guard access to the generator.
284      *
285      * @param lock Lock guarding access to the generator.
286      * @param rng Random generator.
287      * @param array Array data.
288      * @param start Start (inclusive).
289      * @param end End (exclusive).
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      * Baseline for a JMH method call with no return value.
304      */
305     @Benchmark
306     public void baselineVoid() {
307         // Do nothing, this is a baseline
308     }
309 
310     /**
311      * Baseline for a JMH method call returning an {@code int[]}.
312      *
313      * @return the value
314      */
315     @Benchmark
316     public int[] baselineIntArray() {
317         return intValue;
318     }
319 
320     /**
321      * Baseline for a JMH method call returning an {@code long[]}.
322      *
323      * @return the value
324      */
325     @Benchmark
326     public long[] baselineLongArray() {
327         return longValue;
328     }
329 
330     // The following methods use underscores to make parsing the results output easier.
331     // They are not documented as the names are self-documenting.
332 
333     // CHECKSTYLE: stop MethodName
334 
335     /**
336      * @param sources Source of randomness.
337      * @param sizes Size of the seed.
338      * @return the seed
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      * @param sources Source of randomness.
352      * @param sizes Size of the seed.
353      * @return the seed
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      * @param sources Source of randomness.
367      * @param sizes Size of the seed.
368      * @return the seed
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      * @param sources Source of randomness.
382      * @param sizes Size of the seed.
383      * @return the seed
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      * @param sources Source of randomness.
397      * @param sizes Size of the seed.
398      * @return the seed
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      * @param sources Source of randomness.
412      * @param sizes Size of the seed.
413      * @return the seed
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      * @param sources Source of randomness.
427      * @param sizes Size of the seed.
428      * @return the seed
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      * @param sources Source of randomness.
442      * @param sizes Size of the seed.
443      * @return the seed
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      * @param sources Source of randomness.
457      * @param sizes Size of the seed and compute blocks.
458      * @return the seed
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      * @param sources Source of randomness.
472      * @param sizes Size of the seed and compute blocks.
473      * @return the seed
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      * @param sources Source of randomness.
487      * @param sizes Size of the seed and compute blocks.
488      * @return the seed
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      * @param sources Source of randomness.
502      * @param sizes Size of the seed and compute blocks.
503      * @return the seed
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      * @param sources Source of randomness.
517      * @param sizes Size of the seed and compute blocks.
518      * @return the seed
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      * @param sources Source of randomness.
532      * @param sizes Size of the seed and compute blocks.
533      * @return the seed
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      * @param sources Source of randomness.
547      * @param sizes Size of the seed.
548      * @return the seed
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      * @param sources Source of randomness.
563      * @param sizes Size of the seed.
564      * @return the seed
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      * @param sources Source of randomness.
579      * @param sizes Size of the seed.
580      * @return the seed
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      * @param sources Source of randomness.
595      * @param sizes Size of the seed.
596      * @return the seed
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      * @param sources Source of randomness.
611      * @param sizes Size of the seed.
612      * @return the seed
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      * @param sources Source of randomness.
627      * @param sizes Size of the seed.
628      * @return the seed
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      * @param sources Source of randomness.
643      * @param sizes Size of the seed and compute blocks.
644      * @return the seed
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      * @param sources Source of randomness.
659      * @param sizes Size of the seed and compute blocks.
660      * @return the seed
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      * @param sources Source of randomness.
675      * @param sizes Size of the seed and compute blocks.
676      * @return the seed
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      * @param sources Source of randomness.
691      * @param sizes Size of the seed and compute blocks.
692      * @return the seed
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      * @param sources Source of randomness.
707      * @param sizes Size of the seed and compute blocks.
708      * @return the seed
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      * @param sources Source of randomness.
723      * @param sizes Size of the seed and compute blocks.
724      * @return the seed
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 }