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.openjdk.jmh.annotations.Benchmark;
21 import org.openjdk.jmh.annotations.BenchmarkMode;
22 import org.openjdk.jmh.annotations.Mode;
23 import org.openjdk.jmh.annotations.Warmup;
24 import org.openjdk.jmh.annotations.Measurement;
25 import org.openjdk.jmh.annotations.State;
26 import org.openjdk.jmh.annotations.Threads;
27 import org.openjdk.jmh.annotations.Fork;
28 import org.openjdk.jmh.annotations.Scope;
29 import org.openjdk.jmh.annotations.Param;
30 import org.openjdk.jmh.annotations.Setup;
31 import org.openjdk.jmh.annotations.OutputTimeUnit;
32
33 import java.util.concurrent.ThreadLocalRandom;
34 import java.util.concurrent.TimeUnit;
35
36 import org.apache.commons.rng.UniformRandomProvider;
37 import org.apache.commons.rng.simple.RandomSource;
38 import org.apache.commons.rng.simple.ThreadLocalRandomSource;
39
40
41
42
43
44 @BenchmarkMode(Mode.AverageTime)
45 @OutputTimeUnit(TimeUnit.NANOSECONDS)
46 @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
47 @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
48 @State(Scope.Benchmark)
49 @Fork(value = 1, jvmArgs = {"-server", "-Xms128M", "-Xmx128M"})
50 public class ThreadLocalPerformance {
51
52
53
54 @Param({"0", "1", "10", "100"})
55 private int numValues;
56
57
58
59
60 @State(Scope.Benchmark)
61 public static class Sources {
62
63 protected RandomSource randomSource;
64
65
66
67
68 @Param({"SPLIT_MIX_64"})
69 private String randomSourceName;
70
71
72
73
74 public RandomSource getRandomSource() {
75 return randomSource;
76 }
77
78
79 @Setup
80 public void setup() {
81 randomSource = RandomSource.valueOf(randomSourceName);
82 }
83 }
84
85
86
87
88 @State(Scope.Benchmark)
89 public static class LocalSources extends Sources {
90
91 private ThreadLocal<UniformRandomProvider> rng;
92
93
94
95
96 public UniformRandomProvider getRNG() {
97 return rng.get();
98 }
99
100
101 @Override
102 @Setup
103 public void setup() {
104 super.setup();
105
106 rng = new ThreadLocal<UniformRandomProvider>() {
107 @Override
108 protected UniformRandomProvider initialValue() {
109 return randomSource.create();
110 }
111 };
112 }
113 }
114
115
116
117
118 @Benchmark
119 @Threads(4)
120 public long threadLocalRandom() {
121 final ThreadLocalRandom rng = ThreadLocalRandom.current();
122 long result = 0;
123 for (int i = 0; i < numValues; i++) {
124 result = result ^ rng.nextLong();
125 }
126 return result;
127 }
128
129
130
131
132 @Benchmark
133 @Threads(4)
134 public long threadLocalRandomWrapped() {
135 final ThreadLocalRandom rand = ThreadLocalRandom.current();
136 final UniformRandomProvider rng = rand::nextLong;
137 long result = 0;
138 for (int i = 0; i < numValues; i++) {
139 result = result ^ rng.nextLong();
140 }
141 return result;
142 }
143
144
145
146
147
148 @Benchmark
149 @Threads(4)
150 public long randomSourceCreate(Sources sources) {
151 final UniformRandomProvider rng = sources.getRandomSource().create();
152 long result = 0;
153 for (int i = 0; i < numValues; i++) {
154 result = result ^ rng.nextLong();
155 }
156 return result;
157 }
158
159
160
161
162
163 @Benchmark
164 @Threads(4)
165 public long threadLocalRandomSourceCurrent(Sources sources) {
166 final UniformRandomProvider rng = ThreadLocalRandomSource.current(sources.getRandomSource());
167 long result = 0;
168 for (int i = 0; i < numValues; i++) {
169 result = result ^ rng.nextLong();
170 }
171 return result;
172 }
173
174
175
176
177
178 @Benchmark
179 @Threads(4)
180 public long threadLocalUniformRandomProvider(LocalSources localSources) {
181 final UniformRandomProvider rng = localSources.getRNG();
182 long result = 0;
183 for (int i = 0; i < numValues; i++) {
184 result = result ^ rng.nextLong();
185 }
186 return result;
187 }
188 }