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.Fork;
 28 import org.openjdk.jmh.annotations.Measurement;
 29 import org.openjdk.jmh.annotations.Mode;
 30 import org.openjdk.jmh.annotations.OutputTimeUnit;
 31 import org.openjdk.jmh.annotations.Scope;
 32 import org.openjdk.jmh.annotations.State;
 33 import org.openjdk.jmh.annotations.Warmup;
 34 
 35 import java.util.concurrent.TimeUnit;
 36 
 37 /**
 38  * evaluates invocation costs.
 39  *
 40  * @author Sergey Kuksenko (sergey.kuksenko@oracle.com)
 41  */
 42 @BenchmarkMode(Mode.AverageTime)
 43 @OutputTimeUnit(TimeUnit.NANOSECONDS)
 44 @State(Scope.Thread)
 45 @Warmup(iterations = 4, time = 2)
 46 @Measurement(iterations = 4, time = 2)
 47 @Fork(value = 3)
 48 public class Function0 {
 49 
 50     public interface FunctionI {
 51         int foo();
 52     }
 53 
 54     public interface FunctionL {
 55         Integer foo();
 56     }
 57 
 58     private static int valueI = 40002; // bypass Integer.cache
 59     private static Integer valueL = Integer.valueOf(valueI);
 60 
 61     public int fooInstanceI() {
 62         return valueI;
 63     }
 64 
 65     public static int fooStaticI() {
 66         return valueI;
 67     }
 68 
 69     public Integer fooInstanceL() {
 70         return valueL;
 71     }
 72 
 73     public static Integer fooStaticL() {
 74         return valueL;
 75     }
 76 
 77     @Benchmark
 78     public int baselineI() {
 79         return fooInstanceI();
 80     }
 81 
 82     @Benchmark
 83     public Integer baselineL() {
 84         return fooInstanceL();
 85     }
 86 
 87     public final FunctionI anonymI =
 88             new FunctionI() {
 89                 @Override
 90                 public int foo() {
 91                     return valueI;
 92                 }
 93             };
 94 
 95     public final FunctionL anonymL =
 96             new FunctionL() {
 97                 @Override
 98                 public Integer foo() {
 99                     return valueL;
100                 }
101             };
102 
103     @Benchmark
104     public int innerI() {
105         return anonymI.foo();
106     }
107 
108     @Benchmark
109     public Integer innerL() {
110         return anonymL.foo();
111     }
112 
113     public final FunctionI lambdaI = () -> valueI;
114 
115     public final FunctionL lambdaL = () -> valueL;
116 
117     @Benchmark
118     public int lambdaI() {
119         return lambdaI.foo();
120     }
121 
122     @Benchmark
123     public Integer lambdaL() {
124         return lambdaL.foo();
125     }
126 
127     public final FunctionI mref_I2I  = Function0::fooStaticI;
128     @SuppressWarnings("initialization")
129     public final FunctionI mref_I2I_bound = this::fooInstanceI;
130 
131     public final FunctionL mref_I2L  = Function0::fooStaticI;
132     @SuppressWarnings("initialization")
133     public final FunctionL mref_I2L_bound = this::fooInstanceI;
134 
135     public final FunctionI mref_L2I  = Function0::fooStaticL;
136     @SuppressWarnings("initialization")
137     public final FunctionI mref_L2I_bound = this::fooInstanceL;
138 
139     public final FunctionL mref_L2L  = Function0::fooStaticL;
140     @SuppressWarnings("initialization")
141     public final FunctionL mref_L2L_bound = this::fooInstanceL;
142 
143     // mref naming
144     // sig1_sig2 where:
145     // sig1 - signature of the method referenced by method ref
146     // sig2 - FuntionalInterface signature
147 
148     @Benchmark
149     public int mrefI_I() {
150         return mref_I2I.foo();
151     }
152 
153     @Benchmark
154     public int mref_bndI_I() {
155         return mref_I2I_bound.foo();
156     }
157 
158     @Benchmark
159     public Integer mrefI_L() {
160         return mref_I2L.foo();
161     }
162 
163     @Benchmark
164     public Integer mref_bndI_L() {
165         return mref_I2L_bound.foo();
166     }
167 
168     @Benchmark
169     public int mrefL_I() {
170         return mref_L2I.foo();
171     }
172 
173     @Benchmark
174     public int mref_bndL_I() {
175         return mref_L2I_bound.foo();
176     }
177 
178     @Benchmark
179     public Integer mrefL_L() {
180         return mref_L2L.foo();
181     }
182 
183     @Benchmark
184     public Integer mref_bndL_L() {
185         return mref_L2L_bound.foo();
186     }
187 
188 
189 }
190