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.Mode;
29 import org.openjdk.jmh.annotations.OperationsPerInvocation;
30 import org.openjdk.jmh.annotations.OutputTimeUnit;
31 import org.openjdk.jmh.annotations.Scope;
32 import org.openjdk.jmh.annotations.Setup;
33 import org.openjdk.jmh.annotations.State;
34 import org.openjdk.jmh.infra.Blackhole;
35 
36 import java.util.concurrent.ThreadLocalRandom;
37 import java.util.concurrent.TimeUnit;
38 
39 /**
40  * evaluates invocation costs.
41  *
42  * @author Sergey Kuksenko (sergey.kuksenko@oracle.com)
43  */
44 @BenchmarkMode(Mode.AverageTime)
45 @OutputTimeUnit(TimeUnit.NANOSECONDS)
46 @State(Scope.Thread)
47 public class Function1 {
48 
49     public interface FunctionII {
foo(int x)50         int foo(int x);
51     }
52 
53     public interface FunctionIL {
foo(Integer x)54         int foo(Integer x);
55     }
56 
57     public interface FunctionLL {
foo(Integer x)58         Integer foo(Integer x);
59     }
60 
61     private static final int LIMIT = 1024;
62 
63     private final int[]     dataI = new int[LIMIT + 1];
64     private final Integer[] dataL = new Integer[LIMIT + 1];
65 
66     @Setup(Level.Iteration)
setup()67     public void setup() {
68         for (int i = 0; i < dataI.length; i++) {
69             int value = ThreadLocalRandom.current().nextInt(10001,420000); // bypass Integer.cache
70             dataI[i] = value;
71             dataL[i] = value;
72         }
73     }
74 
75 
76 
fooInstanceII(int x)77     public int fooInstanceII(int x) {
78         return x;
79     }
80 
fooStaticII(int x)81     public static int fooStaticII(int x) {
82         return x;
83     }
84 
fooInstanceIL(Integer v)85     public int fooInstanceIL(Integer v) {
86         return v;
87     }
88 
fooStaticIL(Integer v)89     public static int fooStaticIL(Integer v) {
90         return v;
91     }
92 
fooInstanceLL(Integer v)93     public Integer fooInstanceLL(Integer v) {
94         return v;
95     }
96 
fooStaticLL(Integer v)97     public static Integer fooStaticLL(Integer v) {
98         return v;
99     }
100 
101     @Benchmark
102     @OperationsPerInvocation(LIMIT)
baselineII(Blackhole bh)103     public void baselineII(Blackhole bh) {
104         for (int i = 0; i < LIMIT; i++) {
105             bh.consume(fooInstanceII(dataI[i]));
106         }
107     }
108 
109     @Benchmark
110     @OperationsPerInvocation(LIMIT)
baselineIL(Blackhole bh)111     public void baselineIL(Blackhole bh) {
112         for (int i = 0; i < LIMIT; i++) {
113             bh.consume(fooInstanceIL(dataL[i]));
114         }
115     }
116 
117     @Benchmark
118     @OperationsPerInvocation(LIMIT)
baselineLL(Blackhole bh)119     public void baselineLL(Blackhole bh) {
120         for (int i = 0; i < LIMIT; i++) {
121             bh.consume(fooInstanceLL(dataL[i]));
122         }
123     }
124 
125     public final FunctionII anonymII =
126             new FunctionII() {
127                 @Override
128                 public int foo(int x) {
129                     return x;
130                 }
131             };
132 
133     public final FunctionIL anonymIL =
134             new FunctionIL() {
135                 @Override
136                 public int foo(Integer v) {
137                     return v;
138                 }
139             };
140 
141     public final FunctionLL anonymLL =
142             new FunctionLL() {
143                 @Override
144                 public Integer foo(Integer v) {
145                     return v;
146                 }
147             };
148 
149 
150     @Benchmark
151     @OperationsPerInvocation(LIMIT)
innerII(Blackhole bh)152     public void innerII(Blackhole bh) {
153         processII(bh, anonymII);
154     }
155 
156     @Benchmark
157     @OperationsPerInvocation(LIMIT)
innerIL(Blackhole bh)158     public void innerIL(Blackhole bh) {
159         processIL(bh, anonymIL);
160     }
161 
162     @Benchmark
163     @OperationsPerInvocation(LIMIT)
innerLL(Blackhole bh)164     public void innerLL(Blackhole bh) {
165         processLL(bh, anonymLL);
166     }
167 
168     public final FunctionII lambdaII =  x -> x;
169 
170     public final FunctionIL lambdaIL =  v -> v;
171 
172     public final FunctionLL lambdaLL =  v -> v;
173 
174 
175     @Benchmark
176     @OperationsPerInvocation(LIMIT)
lambdaII(Blackhole bh)177     public void lambdaII(Blackhole bh) {
178         processII(bh, lambdaII);
179     }
180 
181     @Benchmark
182     @OperationsPerInvocation(LIMIT)
lambdaIL(Blackhole bh)183     public void lambdaIL(Blackhole bh) {
184         processIL(bh, lambdaIL);
185     }
186 
187     @Benchmark
188     @OperationsPerInvocation(LIMIT)
lambdaLL(Blackhole bh)189     public void lambdaLL(Blackhole bh) {
190         processLL(bh, lambdaLL);
191     }
192 
193 
194 
195     public final FunctionII mref_II2II  = Function1::fooStaticII;
196     public final FunctionII mref_II2II_bound = this::fooInstanceII;
197     public final FunctionIL mref_II2IL  = Function1::fooStaticII;
198     public final FunctionIL mref_II2IL_bound = this::fooInstanceII;
199     public final FunctionLL mref_II2LL  = Function1::fooStaticII;
200     public final FunctionLL mref_II2LL_bound = this::fooInstanceII;
201 
202     public final FunctionII mref_IL2II  = Function1::fooStaticIL;
203     public final FunctionII mref_IL2II_bound = this::fooInstanceIL;
204     public final FunctionIL mref_IL2IL  = Function1::fooStaticIL;
205     public final FunctionIL mref_IL2IL_bound = this::fooInstanceIL;
206     public final FunctionLL mref_IL2LL  = Function1::fooStaticIL;
207     public final FunctionLL mref_IL2LL_bound = this::fooInstanceIL;
208 
209     public final FunctionII mref_LL2II  = Function1::fooStaticLL;
210     public final FunctionII mref_LL2II_bound = this::fooInstanceLL;
211     public final FunctionIL mref_LL2IL  = Function1::fooStaticLL;
212     public final FunctionIL mref_LL2IL_bound = this::fooInstanceLL;
213     public final FunctionLL mref_LL2LL  = Function1::fooStaticLL;
214     public final FunctionLL mref_LL2LL_bound = this::fooInstanceLL;
215 
216 
217     // mref naming
218     // sig1_sig2 where:
219     // sig1 - signature of the method referenced by method ref
220     // sig2 - FuntionalInterface signature
221 
222     @Benchmark
223     @OperationsPerInvocation(LIMIT)
mrefII_II(Blackhole bh)224     public void mrefII_II(Blackhole bh) {
225         processII(bh, mref_II2II);
226     }
227 
228     @Benchmark
229     @OperationsPerInvocation(LIMIT)
mref_bndII_II(Blackhole bh)230     public void mref_bndII_II(Blackhole bh) {
231         processII(bh, mref_II2II_bound);
232     }
233 
234     @Benchmark
235     @OperationsPerInvocation(LIMIT)
mrefII_IL(Blackhole bh)236     public void mrefII_IL(Blackhole bh) {
237         processIL(bh, mref_II2IL);
238     }
239 
240     @Benchmark
241     @OperationsPerInvocation(LIMIT)
mref_bndII_IL(Blackhole bh)242     public void mref_bndII_IL(Blackhole bh) {
243         processIL(bh, mref_II2IL_bound);
244     }
245 
246     @Benchmark
247     @OperationsPerInvocation(LIMIT)
mrefII_LL(Blackhole bh)248     public void mrefII_LL(Blackhole bh) {
249         processLL(bh, mref_II2LL);
250     }
251 
252     @Benchmark
253     @OperationsPerInvocation(LIMIT)
mref_bndII_LL(Blackhole bh)254     public void mref_bndII_LL(Blackhole bh) {
255         processLL(bh, mref_II2LL_bound);
256     }
257 
258     @Benchmark
259     @OperationsPerInvocation(LIMIT)
mrefIL_II(Blackhole bh)260     public void mrefIL_II(Blackhole bh) {
261         processII(bh, mref_IL2II);
262     }
263 
264     @Benchmark
265     @OperationsPerInvocation(LIMIT)
mref_bndIL_II(Blackhole bh)266     public void mref_bndIL_II(Blackhole bh) {
267         processII(bh, mref_IL2II_bound);
268     }
269 
270     @Benchmark
271     @OperationsPerInvocation(LIMIT)
mrefIL_IL(Blackhole bh)272     public void mrefIL_IL(Blackhole bh) {
273         processIL(bh, mref_IL2IL);
274     }
275 
276     @Benchmark
277     @OperationsPerInvocation(LIMIT)
mref_bndIL_IL(Blackhole bh)278     public void mref_bndIL_IL(Blackhole bh) {
279         processIL(bh, mref_IL2IL_bound);
280     }
281 
282     @Benchmark
283     @OperationsPerInvocation(LIMIT)
mrefIL_LL(Blackhole bh)284     public void mrefIL_LL(Blackhole bh) {
285         processLL(bh, mref_IL2LL);
286     }
287 
288     @Benchmark
289     @OperationsPerInvocation(LIMIT)
mref_bndIL_LL(Blackhole bh)290     public void mref_bndIL_LL(Blackhole bh) {
291         processLL(bh, mref_IL2LL_bound);
292     }
293 
294     @Benchmark
295     @OperationsPerInvocation(LIMIT)
mrefLL_II(Blackhole bh)296     public void mrefLL_II(Blackhole bh) {
297         processII(bh, mref_LL2II);
298     }
299 
300     @Benchmark
301     @OperationsPerInvocation(LIMIT)
mref_bndLL_II(Blackhole bh)302     public void mref_bndLL_II(Blackhole bh) {
303         processII(bh, mref_LL2II_bound);
304     }
305 
306     @Benchmark
307     @OperationsPerInvocation(LIMIT)
mrefLL_IL(Blackhole bh)308     public void mrefLL_IL(Blackhole bh) {
309         processIL(bh, mref_LL2IL);
310     }
311 
312     @Benchmark
313     @OperationsPerInvocation(LIMIT)
mref_bndLL_IL(Blackhole bh)314     public void mref_bndLL_IL(Blackhole bh) {
315         processIL(bh, mref_LL2IL_bound);
316     }
317 
318     @Benchmark
319     @OperationsPerInvocation(LIMIT)
mrefLL_LL(Blackhole bh)320     public void mrefLL_LL(Blackhole bh) {
321         processLL(bh, mref_LL2LL);
322     }
323 
324     @Benchmark
325     @OperationsPerInvocation(LIMIT)
mref_bndLL_LL(Blackhole bh)326     public void mref_bndLL_LL(Blackhole bh) {
327         processLL(bh, mref_LL2LL_bound);
328     }
329 
330 
processII(Blackhole bh, FunctionII func)331     private void processII(Blackhole bh, FunctionII func) {
332         for (int i = 0; i < LIMIT; i++) {
333             bh.consume(func.foo(dataI[i]));
334         }
335     }
336 
processIL(Blackhole bh, FunctionIL func)337     private void processIL(Blackhole bh, FunctionIL func) {
338         for (int i = 0; i < LIMIT; i++) {
339             bh.consume(func.foo(dataL[i]));
340         }
341     }
342 
processLL(Blackhole bh, FunctionLL func)343     private void processLL(Blackhole bh, FunctionLL func) {
344         for (int i = 0; i < LIMIT; i++) {
345             bh.consume(func.foo(dataL[i]));
346         }
347     }
348 
349 }
350 
351