1 /*
2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package org.openjdk.bench.vm.lambda.invoke;
24
25 import org.openjdk.jmh.annotations.Benchmark;
26 import org.openjdk.jmh.annotations.BenchmarkMode;
27 import org.openjdk.jmh.annotations.Level;
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.OperationsPerInvocation;
32 import org.openjdk.jmh.annotations.OutputTimeUnit;
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 import java.util.concurrent.ThreadLocalRandom;
40 import java.util.concurrent.TimeUnit;
41
42 /**
43 * evaluates invocation costs.
44 *
45 * @author Sergey Kuksenko (sergey.kuksenko@oracle.com)
46 */
47 @BenchmarkMode(Mode.AverageTime)
48 @OutputTimeUnit(TimeUnit.NANOSECONDS)
49 @State(Scope.Thread)
50 @Warmup(iterations = 4, time = 2)
51 @Measurement(iterations = 4, time = 2)
52 @Fork(value = 3)
53 public class Function1 {
54
55 public interface FunctionII {
56 int foo(int x);
57 }
58
59 public interface FunctionIL {
60 int foo(Integer x);
61 }
62
63 public interface FunctionLL {
64 Integer foo(Integer x);
65 }
66
67 private static final int LIMIT = 1024;
68
69 private final int[] dataI = new int[LIMIT + 1];
70 private final Integer[] dataL = new Integer[LIMIT + 1];
71
72 @Setup(Level.Iteration)
73 public void setup() {
74 for (int i = 0; i < dataI.length; i++) {
75 int value = ThreadLocalRandom.current().nextInt(10001,420000); // bypass Integer.cache
76 dataI[i] = value;
77 dataL[i] = value;
78 }
79 }
80
81
82
83 public int fooInstanceII(int x) {
84 return x;
85 }
86
87 public static int fooStaticII(int x) {
88 return x;
89 }
90
91 public int fooInstanceIL(Integer v) {
92 return v;
93 }
94
95 public static int fooStaticIL(Integer v) {
96 return v;
97 }
98
99 public Integer fooInstanceLL(Integer v) {
100 return v;
101 }
102
103 public static Integer fooStaticLL(Integer v) {
104 return v;
105 }
106
107 @Benchmark
108 @OperationsPerInvocation(LIMIT)
109 public void baselineII(Blackhole bh) {
110 for (int i = 0; i < LIMIT; i++) {
111 bh.consume(fooInstanceII(dataI[i]));
112 }
113 }
114
115 @Benchmark
116 @OperationsPerInvocation(LIMIT)
117 public void baselineIL(Blackhole bh) {
118 for (int i = 0; i < LIMIT; i++) {
119 bh.consume(fooInstanceIL(dataL[i]));
120 }
121 }
122
123 @Benchmark
124 @OperationsPerInvocation(LIMIT)
125 public void baselineLL(Blackhole bh) {
126 for (int i = 0; i < LIMIT; i++) {
127 bh.consume(fooInstanceLL(dataL[i]));
128 }
129 }
130
131 public final FunctionII anonymII =
132 new FunctionII() {
133 @Override
134 public int foo(int x) {
135 return x;
136 }
137 };
138
139 public final FunctionIL anonymIL =
140 new FunctionIL() {
141 @Override
142 public int foo(Integer v) {
143 return v;
144 }
145 };
146
147 public final FunctionLL anonymLL =
148 new FunctionLL() {
149 @Override
150 public Integer foo(Integer v) {
151 return v;
152 }
153 };
154
155
156 @Benchmark
157 @OperationsPerInvocation(LIMIT)
158 public void innerII(Blackhole bh) {
159 processII(bh, anonymII);
160 }
161
162 @Benchmark
163 @OperationsPerInvocation(LIMIT)
164 public void innerIL(Blackhole bh) {
165 processIL(bh, anonymIL);
166 }
167
168 @Benchmark
169 @OperationsPerInvocation(LIMIT)
170 public void innerLL(Blackhole bh) {
171 processLL(bh, anonymLL);
172 }
173
174 public final FunctionII lambdaII = x -> x;
175
176 public final FunctionIL lambdaIL = v -> v;
177
178 public final FunctionLL lambdaLL = v -> v;
179
180
181 @Benchmark
182 @OperationsPerInvocation(LIMIT)
183 public void lambdaII(Blackhole bh) {
184 processII(bh, lambdaII);
185 }
186
187 @Benchmark
188 @OperationsPerInvocation(LIMIT)
189 public void lambdaIL(Blackhole bh) {
190 processIL(bh, lambdaIL);
191 }
192
193 @Benchmark
194 @OperationsPerInvocation(LIMIT)
195 public void lambdaLL(Blackhole bh) {
196 processLL(bh, lambdaLL);
197 }
198
199
200
201 public final FunctionII mref_II2II = Function1::fooStaticII;
202 @SuppressWarnings("initialization")
203 public final FunctionII mref_II2II_bound = this::fooInstanceII;
204 public final FunctionIL mref_II2IL = Function1::fooStaticII;
205 @SuppressWarnings("initialization")
206 public final FunctionIL mref_II2IL_bound = this::fooInstanceII;
207 public final FunctionLL mref_II2LL = Function1::fooStaticII;
208 @SuppressWarnings("initialization")
209 public final FunctionLL mref_II2LL_bound = this::fooInstanceII;
210
211 public final FunctionII mref_IL2II = Function1::fooStaticIL;
212 @SuppressWarnings("initialization")
213 public final FunctionII mref_IL2II_bound = this::fooInstanceIL;
214 public final FunctionIL mref_IL2IL = Function1::fooStaticIL;
215 @SuppressWarnings("initialization")
216 public final FunctionIL mref_IL2IL_bound = this::fooInstanceIL;
217 public final FunctionLL mref_IL2LL = Function1::fooStaticIL;
218 @SuppressWarnings("initialization")
219 public final FunctionLL mref_IL2LL_bound = this::fooInstanceIL;
220
221 public final FunctionII mref_LL2II = Function1::fooStaticLL;
222 @SuppressWarnings("initialization")
223 public final FunctionII mref_LL2II_bound = this::fooInstanceLL;
224 public final FunctionIL mref_LL2IL = Function1::fooStaticLL;
225 @SuppressWarnings("initialization")
226 public final FunctionIL mref_LL2IL_bound = this::fooInstanceLL;
227 public final FunctionLL mref_LL2LL = Function1::fooStaticLL;
228 @SuppressWarnings("initialization")
229 public final FunctionLL mref_LL2LL_bound = this::fooInstanceLL;
230
231
232 // mref naming
233 // sig1_sig2 where:
234 // sig1 - signature of the method referenced by method ref
235 // sig2 - FuntionalInterface signature
236
237 @Benchmark
238 @OperationsPerInvocation(LIMIT)
239 public void mrefII_II(Blackhole bh) {
240 processII(bh, mref_II2II);
241 }
242
243 @Benchmark
244 @OperationsPerInvocation(LIMIT)
245 public void mref_bndII_II(Blackhole bh) {
246 processII(bh, mref_II2II_bound);
247 }
248
249 @Benchmark
250 @OperationsPerInvocation(LIMIT)
251 public void mrefII_IL(Blackhole bh) {
252 processIL(bh, mref_II2IL);
253 }
254
255 @Benchmark
256 @OperationsPerInvocation(LIMIT)
257 public void mref_bndII_IL(Blackhole bh) {
258 processIL(bh, mref_II2IL_bound);
259 }
260
261 @Benchmark
262 @OperationsPerInvocation(LIMIT)
263 public void mrefII_LL(Blackhole bh) {
264 processLL(bh, mref_II2LL);
265 }
266
267 @Benchmark
268 @OperationsPerInvocation(LIMIT)
269 public void mref_bndII_LL(Blackhole bh) {
270 processLL(bh, mref_II2LL_bound);
271 }
272
273 @Benchmark
274 @OperationsPerInvocation(LIMIT)
275 public void mrefIL_II(Blackhole bh) {
276 processII(bh, mref_IL2II);
277 }
278
279 @Benchmark
280 @OperationsPerInvocation(LIMIT)
281 public void mref_bndIL_II(Blackhole bh) {
282 processII(bh, mref_IL2II_bound);
283 }
284
285 @Benchmark
286 @OperationsPerInvocation(LIMIT)
287 public void mrefIL_IL(Blackhole bh) {
288 processIL(bh, mref_IL2IL);
289 }
290
291 @Benchmark
292 @OperationsPerInvocation(LIMIT)
293 public void mref_bndIL_IL(Blackhole bh) {
294 processIL(bh, mref_IL2IL_bound);
295 }
296
297 @Benchmark
298 @OperationsPerInvocation(LIMIT)
299 public void mrefIL_LL(Blackhole bh) {
300 processLL(bh, mref_IL2LL);
301 }
302
303 @Benchmark
304 @OperationsPerInvocation(LIMIT)
305 public void mref_bndIL_LL(Blackhole bh) {
306 processLL(bh, mref_IL2LL_bound);
307 }
308
309 @Benchmark
310 @OperationsPerInvocation(LIMIT)
311 public void mrefLL_II(Blackhole bh) {
312 processII(bh, mref_LL2II);
313 }
314
315 @Benchmark
316 @OperationsPerInvocation(LIMIT)
317 public void mref_bndLL_II(Blackhole bh) {
318 processII(bh, mref_LL2II_bound);
319 }
320
321 @Benchmark
322 @OperationsPerInvocation(LIMIT)
323 public void mrefLL_IL(Blackhole bh) {
324 processIL(bh, mref_LL2IL);
325 }
326
327 @Benchmark
328 @OperationsPerInvocation(LIMIT)
329 public void mref_bndLL_IL(Blackhole bh) {
330 processIL(bh, mref_LL2IL_bound);
331 }
332
333 @Benchmark
334 @OperationsPerInvocation(LIMIT)
335 public void mrefLL_LL(Blackhole bh) {
336 processLL(bh, mref_LL2LL);
337 }
338
339 @Benchmark
340 @OperationsPerInvocation(LIMIT)
341 public void mref_bndLL_LL(Blackhole bh) {
342 processLL(bh, mref_LL2LL_bound);
343 }
344
345
346 private void processII(Blackhole bh, FunctionII func) {
347 for (int i = 0; i < LIMIT; i++) {
348 bh.consume(func.foo(dataI[i]));
349 }
350 }
351
352 private void processIL(Blackhole bh, FunctionIL func) {
353 for (int i = 0; i < LIMIT; i++) {
354 bh.consume(func.foo(dataL[i]));
355 }
356 }
357
358 private void processLL(Blackhole bh, FunctionLL func) {
359 for (int i = 0; i < LIMIT; i++) {
360 bh.consume(func.foo(dataL[i]));
361 }
362 }
363
364 }
365