1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.numbers.examples.jmh.core;
18
19 import java.util.concurrent.TimeUnit;
20 import java.util.function.ToDoubleBiFunction;
21 import java.util.function.ToDoubleFunction;
22
23 import org.apache.commons.numbers.core.Sum;
24 import org.apache.commons.rng.UniformRandomProvider;
25 import org.apache.commons.rng.simple.RandomSource;
26 import org.openjdk.jmh.annotations.Benchmark;
27 import org.openjdk.jmh.annotations.BenchmarkMode;
28 import org.openjdk.jmh.annotations.Fork;
29 import org.openjdk.jmh.annotations.Measurement;
30 import org.openjdk.jmh.annotations.Mode;
31 import org.openjdk.jmh.annotations.OutputTimeUnit;
32 import org.openjdk.jmh.annotations.Param;
33 import org.openjdk.jmh.annotations.Scope;
34 import org.openjdk.jmh.annotations.Setup;
35 import org.openjdk.jmh.annotations.State;
36 import org.openjdk.jmh.annotations.Warmup;
37 import org.openjdk.jmh.infra.Blackhole;
38
39
40
41
42 @BenchmarkMode(Mode.AverageTime)
43 @OutputTimeUnit(TimeUnit.NANOSECONDS)
44 @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
45 @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
46 @State(Scope.Benchmark)
47 @Fork(value = 1, jvmArgs = {"-server", "-Xms512M", "-Xmx512M"})
48 public class SumPerformance {
49
50
51
52
53 private static final long SEED = System.currentTimeMillis();
54
55
56
57 @State(Scope.Benchmark)
58 public static class ArrayInput {
59
60
61 @Param("100000")
62 private int samples;
63
64
65 @Param("50")
66 private int len;
67
68
69 @Param("-550")
70 private int minExp;
71
72
73 @Param("+550")
74 private int maxExp;
75
76
77 @Param("26")
78 private int expRange;
79
80
81 private double[][] a;
82
83
84 private double[][] b;
85
86
87
88
89 public double[][] getA() {
90 return a;
91 }
92
93
94
95
96 public double[][] getB() {
97 return b;
98 }
99
100
101 @Setup
102 public void createArrays() {
103 final UniformRandomProvider rng = RandomSource.XO_RO_SHI_RO_1024_PP.create(SEED);
104
105 a = new double[samples][];
106 b = new double[samples][];
107 for (int i = 0; i < samples; ++i) {
108
109
110 final int vMidExp = rng.nextInt(maxExp - minExp + 1) + minExp;
111 final int vExpRadius = expRange / 2;
112 final int vMinExp = vMidExp - vExpRadius;
113 final int vMaxExp = vMidExp + vExpRadius;
114
115 a[i] = DoubleUtils.randomArray(len, vMinExp, vMaxExp, rng);
116 b[i] = DoubleUtils.randomArray(len, vMinExp, vMaxExp, rng);
117 }
118 }
119 }
120
121
122
123
124
125
126 private static void runSingle(final ArrayInput input, final Blackhole bh,
127 final ToDoubleFunction<double[]> fn) {
128 final double[][] a = input.getA();
129 for (int i = 0; i < a.length; ++i) {
130 bh.consume(fn.applyAsDouble(a[i]));
131 }
132 }
133
134
135
136
137
138
139 private static void runDouble(final ArrayInput input, final Blackhole bh,
140 final ToDoubleBiFunction<double[], double[]> fn) {
141 final double[][] a = input.getA();
142 final double[][] b = input.getB();
143 for (int i = 0; i < a.length; ++i) {
144 bh.consume(fn.applyAsDouble(a[i], b[i]));
145 }
146 }
147
148
149
150
151
152 @Benchmark
153 public void baselineSingle(final ArrayInput input, final Blackhole bh) {
154 runSingle(input, bh, a -> 0d);
155 }
156
157
158
159
160
161 @Benchmark
162 public void baselineDouble(final ArrayInput input, final Blackhole bh) {
163 runDouble(input, bh, (a, b) -> 0d);
164 }
165
166
167
168
169
170 @Benchmark
171 public void sum(final ArrayInput input, final Blackhole bh) {
172 runSingle(input, bh, a -> Sum.of(a).getAsDouble());
173 }
174
175
176
177
178
179 @Benchmark
180 public void sumOfProducts(final ArrayInput input, final Blackhole bh) {
181 runDouble(input, bh, (a, b) -> Sum.ofProducts(a, b).getAsDouble());
182 }
183 }