1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.examples.jmh.euclidean;
18
19 import java.util.concurrent.TimeUnit;
20
21 import org.apache.commons.geometry.euclidean.oned.AffineTransformMatrix1D;
22 import org.apache.commons.geometry.euclidean.oned.Vector1D;
23 import org.apache.commons.geometry.euclidean.threed.AffineTransformMatrix3D;
24 import org.apache.commons.geometry.euclidean.threed.Vector3D;
25 import org.apache.commons.geometry.euclidean.twod.AffineTransformMatrix2D;
26 import org.apache.commons.geometry.euclidean.twod.Vector2D;
27 import org.apache.commons.geometry.examples.jmh.BenchmarkUtils;
28 import org.apache.commons.rng.UniformRandomProvider;
29 import org.apache.commons.rng.simple.RandomSource;
30 import org.openjdk.jmh.annotations.Benchmark;
31 import org.openjdk.jmh.annotations.BenchmarkMode;
32 import org.openjdk.jmh.annotations.Fork;
33 import org.openjdk.jmh.annotations.Level;
34 import org.openjdk.jmh.annotations.Measurement;
35 import org.openjdk.jmh.annotations.Mode;
36 import org.openjdk.jmh.annotations.OutputTimeUnit;
37 import org.openjdk.jmh.annotations.Param;
38 import org.openjdk.jmh.annotations.Scope;
39 import org.openjdk.jmh.annotations.Setup;
40 import org.openjdk.jmh.annotations.State;
41 import org.openjdk.jmh.annotations.Warmup;
42
43
44
45
46
47 @BenchmarkMode(Mode.AverageTime)
48 @OutputTimeUnit(TimeUnit.NANOSECONDS)
49 @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
50 @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
51 @Fork(value = 1, jvmArgs = {"-server", "-Xms512M", "-Xmx512M"})
52 public class AffineTransformMatrixPerformance {
53
54
55
56 @State(Scope.Thread)
57 public static class TransformArrayInput {
58
59
60 @Param({"6000", "600000"})
61 private int size;
62
63
64 private double[] array;
65
66
67
68
69 public int getSize() {
70 return size;
71 }
72
73
74
75
76 public double[] getArray() {
77 return array;
78 }
79
80
81
82 @Setup(Level.Iteration)
83 public void setup() {
84 final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
85
86 array = new double[size];
87
88 for (int i = 0; i < array.length; ++i) {
89 array[i] = BenchmarkUtils.randomDouble(rand);
90 }
91 }
92 }
93
94
95
96 @State(Scope.Thread)
97 public static class TransformMatrixInput1D {
98
99
100 private AffineTransformMatrix1D transform;
101
102
103
104
105 public AffineTransformMatrix1D getTransform() {
106 return transform;
107 }
108
109
110 @Setup
111 public void setup() {
112 final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
113
114 transform = AffineTransformMatrix1D.of(BenchmarkUtils.randomDoubleArray(2, rand));
115 }
116 }
117
118
119
120 @State(Scope.Thread)
121 public static class TransformMatrixInput2D {
122
123
124 private AffineTransformMatrix2D transform;
125
126
127
128
129 public AffineTransformMatrix2D getTransform() {
130 return transform;
131 }
132
133
134 @Setup
135 public void setup() {
136 final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
137
138 transform = AffineTransformMatrix2D.of(BenchmarkUtils.randomDoubleArray(6, rand));
139 }
140 }
141
142
143
144 @State(Scope.Thread)
145 public static class TransformMatrixInput3D {
146
147
148 private AffineTransformMatrix3D transform;
149
150
151
152
153 public AffineTransformMatrix3D getTransform() {
154 return transform;
155 }
156
157
158 @Setup
159 public void setup() {
160 final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
161
162 transform = AffineTransformMatrix3D.of(BenchmarkUtils.randomDoubleArray(12, rand));
163 }
164 }
165
166
167
168
169
170 @Benchmark
171 public double[] baselineArray1D(final TransformArrayInput arrayInput) {
172 final double[] arr = arrayInput.getArray();
173
174 double x;
175 for (int i = 0; i < arr.length; ++i) {
176 x = arr[i];
177
178 arr[i] = x + 1;
179 }
180
181 return arr;
182 }
183
184
185
186
187
188
189
190 @Benchmark
191 public double[] transformArrayAsVectors1D(final TransformArrayInput arrayInput,
192 final TransformMatrixInput1D transformInput) {
193 final double[] arr = arrayInput.getArray();
194 final AffineTransformMatrix1D t = transformInput.getTransform();
195
196 Vector1D in;
197 Vector1D out;
198 for (int i = 0; i < arr.length; ++i) {
199 in = Vector1D.of(arr[i]);
200
201 out = t.apply(in);
202
203 arr[i] = out.getX();
204 }
205
206 return arr;
207 }
208
209
210
211
212
213
214
215 @Benchmark
216 public double[] transformArrayComponents1D(final TransformArrayInput arrayInput,
217 final TransformMatrixInput1D transformInput) {
218 final double[] arr = arrayInput.getArray();
219 final AffineTransformMatrix1D t = transformInput.getTransform();
220
221 double x;
222 for (int i = 0; i < arr.length; ++i) {
223 x = arr[i];
224
225 arr[i] = t.applyX(x);
226 }
227
228 return arr;
229 }
230
231
232
233
234
235 @Benchmark
236 public double[] baselineArray2D(final TransformArrayInput arrayInput) {
237 final double[] arr = arrayInput.getArray();
238
239 double x;
240 double y;
241 for (int i = 0; i < arr.length; i += 2) {
242 x = arr[i];
243 y = arr[i + 1];
244
245 arr[i] = x + 1;
246 arr[i + 1] = y + 1;
247 }
248
249 return arr;
250 }
251
252
253
254
255
256
257
258 @Benchmark
259 public double[] transformArrayAsVectors2D(final TransformArrayInput arrayInput,
260 final TransformMatrixInput2D transformInput) {
261 final double[] arr = arrayInput.getArray();
262 final AffineTransformMatrix2D t = transformInput.getTransform();
263
264 Vector2D in;
265 Vector2D out;
266 for (int i = 0; i < arr.length; i += 2) {
267 in = Vector2D.of(
268 arr[i],
269 arr[i + 1]);
270
271 out = t.apply(in);
272
273 arr[i] = out.getX();
274 arr[i + 1] = out.getY();
275 }
276
277 return arr;
278 }
279
280
281
282
283
284
285
286 @Benchmark
287 public double[] transformArrayComponents2D(final TransformArrayInput arrayInput,
288 final TransformMatrixInput2D transformInput) {
289 final double[] arr = arrayInput.getArray();
290 final AffineTransformMatrix2D t = transformInput.getTransform();
291
292 double x;
293 double y;
294 for (int i = 0; i < arr.length; i += 2) {
295 x = arr[i];
296 y = arr[i + 1];
297
298 arr[i] = t.applyX(x, y);
299 arr[i + 1] = t.applyY(x, y);
300 }
301
302 return arr;
303 }
304
305
306
307
308
309 @Benchmark
310 public double[] baselineArray3D(final TransformArrayInput arrayInput) {
311 final double[] arr = arrayInput.getArray();
312
313 double x;
314 double y;
315 double z;
316 for (int i = 0; i < arr.length; i += 3) {
317 x = arr[i];
318 y = arr[i + 1];
319 z = arr[i + 2];
320
321 arr[i] = x + 1;
322 arr[i + 1] = y + 1;
323 arr[i + 2] = z + 1;
324 }
325
326 return arr;
327 }
328
329
330
331
332
333
334
335 @Benchmark
336 public double[] transformArrayAsVectors3D(final TransformArrayInput arrayInput,
337 final TransformMatrixInput3D transformInput) {
338 final double[] arr = arrayInput.getArray();
339 final AffineTransformMatrix3D t = transformInput.getTransform();
340
341 Vector3D in;
342 Vector3D out;
343 for (int i = 0; i < arr.length; i += 3) {
344 in = Vector3D.of(
345 arr[i],
346 arr[i + 1],
347 arr[i + 2]);
348
349 out = t.apply(in);
350
351 arr[i] = out.getX();
352 arr[i + 1] = out.getY();
353 arr[i + 2] = out.getZ();
354 }
355
356 return arr;
357 }
358
359
360
361
362
363
364
365 @Benchmark
366 public double[] transformArrayComponents3D(final TransformArrayInput arrayInput,
367 final TransformMatrixInput3D transformInput) {
368 final double[] arr = arrayInput.getArray();
369 final AffineTransformMatrix3D t = transformInput.getTransform();
370
371 double x;
372 double y;
373 double z;
374 for (int i = 0; i < arr.length; i += 3) {
375 x = arr[i];
376 y = arr[i + 1];
377 z = arr[i + 2];
378
379 arr[i] = t.applyX(x, y, z);
380 arr[i + 1] = t.applyY(x, y, z);
381 arr[i + 2] = t.applyZ(x, y, z);
382 }
383
384 return arr;
385 }
386 }