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.TimeUnit;
37 import java.util.function.IntUnaryOperator;
38 
39 /**
40  * evaluates N-morphic invocation costs.
41  * N different lambdas each capture 0 variable
42  *
43  * @author Sergey Kuksenko (sergey.kuksenko@oracle.com)
44  */
45 @BenchmarkMode(Mode.AverageTime)
46 @OutputTimeUnit(TimeUnit.NANOSECONDS)
47 @State(Scope.Thread)
48 public class Morph0 {
49 
50 
51     private static final int LIMIT = 16536;
52     private static final int OPS = 4;
53     private static final int OPERATIONS = OPS*LIMIT;
54 
55     // <source of functional interface>_N; where N - how many different targets
56     private IntUnaryOperator[] inner_1;
57     private IntUnaryOperator[] inner_2;
58     private IntUnaryOperator[] inner_4;
59 
60     private IntUnaryOperator[] lambda_1;
61     private IntUnaryOperator[] lambda_2;
62     private IntUnaryOperator[] lambda_4;
63 
64     private IntUnaryOperator[] unbounded_mref_1;
65     private IntUnaryOperator[] unbounded_mref_2;
66     private IntUnaryOperator[] unbounded_mref_4;
67 
68     private IntUnaryOperator[] bounded_mref_1;
69     private IntUnaryOperator[] bounded_mref_2;
70     private IntUnaryOperator[] bounded_mref_4;
71 
72     @Setup(Level.Trial)
setup()73     public void setup() {
74         setup_inner();
75         setup_lambda();
76         setup_unbounded_mref();
77         setup_bounded_mref();
78     }
79 
setup_inner()80     private void setup_inner() {
81         inner_4 =  new IntUnaryOperator[] {
82             new IntUnaryOperator() {
83                 @Override
84                 public int applyAsInt(int x) {
85                     return x + 1;
86                 }
87             },
88             new IntUnaryOperator() {
89                 @Override
90                 public int applyAsInt(int x) {
91                     return x + 2;
92                 }
93             },
94             new IntUnaryOperator() {
95                 @Override
96                 public int applyAsInt(int x) {
97                     return x + 3;
98                 }
99             },
100             new IntUnaryOperator() {
101                 @Override
102                 public int applyAsInt(int x) {
103                     return x + 4;
104                 }
105             },
106         };
107         inner_2 =  new IntUnaryOperator[] { inner_4[0], inner_4[1], inner_4[0], inner_4[1], };
108         inner_1 =  new IntUnaryOperator[] { inner_4[0], inner_4[0], inner_4[0], inner_4[0], };
109     }
110 
setup_lambda()111     private void setup_lambda() {
112         lambda_4 =  new IntUnaryOperator[] {
113                 x -> x + 1,
114                 x -> x + 2,
115                 x -> x + 3,
116                 x -> x + 4,
117         };
118         lambda_2 =  new IntUnaryOperator[] { lambda_4[0], lambda_4[1], lambda_4[0], lambda_4[1], };
119         lambda_1 =  new IntUnaryOperator[] { lambda_4[0], lambda_4[0], lambda_4[0], lambda_4[0], };
120     }
121 
func1(int x)122     public static int func1(int x) {
123         return x + 1;
124     }
125 
func2(int x)126     public static int func2(int x) {
127         return x + 2;
128     }
129 
func3(int x)130     public static int func3(int x) {
131         return x + 3;
132     }
133 
func4(int x)134     public static int func4(int x) {
135         return x + 4;
136     }
137 
setup_unbounded_mref()138     private void setup_unbounded_mref() {
139         unbounded_mref_4 =  new IntUnaryOperator[] {
140                 Morph0::func1,
141                 Morph0::func2,
142                 Morph0::func3,
143                 Morph0::func4,
144         };
145         unbounded_mref_2 =  new IntUnaryOperator[] { unbounded_mref_4[0], unbounded_mref_4[1], unbounded_mref_4[0], unbounded_mref_4[1], };
146         unbounded_mref_1 =  new IntUnaryOperator[] { unbounded_mref_4[0], unbounded_mref_4[0], unbounded_mref_4[0], unbounded_mref_4[0], };
147     }
148 
ifunc1(int x)149     public int ifunc1(int x) {
150         return x + 1;
151     }
152 
ifunc2(int x)153     public int ifunc2(int x) {
154         return x + 2;
155     }
156 
ifunc3(int x)157     public int ifunc3(int x) {
158         return x + 3;
159     }
160 
ifunc4(int x)161     public int ifunc4(int x) {
162         return x + 4;
163     }
164 
setup_bounded_mref()165     private void setup_bounded_mref() {
166         bounded_mref_4 =  new IntUnaryOperator[] {
167                 this::ifunc1,
168                 this::ifunc2,
169                 this::ifunc3,
170                 this::ifunc4,
171         };
172         bounded_mref_2 =  new IntUnaryOperator[] { bounded_mref_4[0], bounded_mref_4[1], bounded_mref_4[0], bounded_mref_4[1], };
173         bounded_mref_1 =  new IntUnaryOperator[] { bounded_mref_4[0], bounded_mref_4[0], bounded_mref_4[0], bounded_mref_4[0], };
174     }
175 
process(Blackhole bh, IntUnaryOperator[] operations)176     public void process(Blackhole bh, IntUnaryOperator[] operations) {
177         for (int i = 0; i < LIMIT; i++) {
178             for (IntUnaryOperator op : operations) {
179                 bh.consume(op.applyAsInt(i));
180             }
181         }
182     }
183 
184     @Benchmark
185     @OperationsPerInvocation(OPERATIONS)
inner1(Blackhole bh)186     public void inner1(Blackhole bh) {
187         process(bh, inner_1);
188     }
189 
190     @Benchmark
191     @OperationsPerInvocation(OPERATIONS)
inner2(Blackhole bh)192     public void inner2(Blackhole bh) {
193         process(bh, inner_2);
194     }
195 
196     @Benchmark
197     @OperationsPerInvocation(OPERATIONS)
inner4(Blackhole bh)198     public void inner4(Blackhole bh) {
199         process(bh, inner_4);
200     }
201 
202     @Benchmark
203     @OperationsPerInvocation(OPERATIONS)
lambda1(Blackhole bh)204     public void lambda1(Blackhole bh) {
205         process(bh, lambda_1);
206     }
207 
208     @Benchmark
209     @OperationsPerInvocation(OPERATIONS)
lambda2(Blackhole bh)210     public void lambda2(Blackhole bh) {
211         process(bh, lambda_2);
212     }
213 
214     @Benchmark
215     @OperationsPerInvocation(OPERATIONS)
lambda4(Blackhole bh)216     public void lambda4(Blackhole bh) {
217         process(bh, lambda_4);
218     }
219 
220     @Benchmark
221     @OperationsPerInvocation(OPERATIONS)
mref1(Blackhole bh)222     public void mref1(Blackhole bh) {
223         process(bh, unbounded_mref_1);
224     }
225 
226     @Benchmark
227     @OperationsPerInvocation(OPERATIONS)
mref2(Blackhole bh)228     public void mref2(Blackhole bh) {
229         process(bh, unbounded_mref_2);
230     }
231 
232     @Benchmark
233     @OperationsPerInvocation(OPERATIONS)
mref4(Blackhole bh)234     public void mref4(Blackhole bh) {
235         process(bh, unbounded_mref_4);
236     }
237 
238     @Benchmark
239     @OperationsPerInvocation(OPERATIONS)
mref_bnd1(Blackhole bh)240     public void mref_bnd1(Blackhole bh) {
241         process(bh, bounded_mref_1);
242     }
243 
244     @Benchmark
245     @OperationsPerInvocation(OPERATIONS)
mref_bnd2(Blackhole bh)246     public void mref_bnd2(Blackhole bh) {
247         process(bh, bounded_mref_2);
248     }
249 
250     @Benchmark
251     @OperationsPerInvocation(OPERATIONS)
mref_bnd4(Blackhole bh)252     public void mref_bnd4(Blackhole bh) {
253         process(bh, bounded_mref_4);
254     }
255 
256 }
257 
258