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.Mode;
28 import org.openjdk.jmh.annotations.OperationsPerInvocation;
29 import org.openjdk.jmh.annotations.OutputTimeUnit;
30 
31 import java.util.concurrent.TimeUnit;
32 import java.util.function.IntBinaryOperator;
33 
34 /**
35  * evaluates invocation costs in case of long recursive chains
36  *
37  * @author Sergey Kuksenko (sergey.kuksenko@oracle.com)
38  */
39 @BenchmarkMode(Mode.AverageTime)
40 @OutputTimeUnit(TimeUnit.NANOSECONDS)
41 public class AckermannI {
42 
43     // ackermann(1,1748)+ ackermann(2,1897)+ ackermann(3,8); == 9999999 calls
44     public static final int Y1 = 1748;
45     public static final int Y2 = 1897;
46     public static final int Y3 = 8;
47 
ack(int x, int y)48     public static int ack(int x, int y) {
49         return x == 0 ?
50                 y + 1 :
51                 (y == 0 ?
52                         ack(x - 1, 1) :
53                         ack(x - 1, ack(x, y - 1)));
54     }
55 
56     @Benchmark
57     @OperationsPerInvocation(9999999)
func()58     public int func() {
59         return ack(1, Y1) + ack(2, Y2) + ack(3, Y3);
60     }
61 
62     public static final IntBinaryOperator inner_ack =
63             new IntBinaryOperator() {
64                 @Override
65                 public int applyAsInt(int x, int y) {
66                     return x == 0 ?
67                             y + 1 :
68                             (y == 0 ?
69                                     inner_ack.applyAsInt(x - 1, 1) :
70                                     inner_ack.applyAsInt(x - 1, inner_ack.applyAsInt(x, y - 1)));
71 
72                 }
73             };
74 
75     @Benchmark
76     @OperationsPerInvocation(9999999)
inner()77     public int inner() {
78         return inner_ack.applyAsInt(1, Y1) + inner_ack.applyAsInt(2, Y2) + inner_ack.applyAsInt(3, Y3);
79     }
80 
81     public static final IntBinaryOperator lambda_ack =
82             (x, y) -> x == 0 ?
83                     y + 1 :
84                     (y == 0 ?
85                             AckermannI.lambda_ack.applyAsInt(x - 1, 1) :
86                             AckermannI.lambda_ack.applyAsInt(x - 1, AckermannI.lambda_ack.applyAsInt(x, y - 1)));
87 
88 
89     @Benchmark
90     @OperationsPerInvocation(9999999)
lambda()91     public int lambda() {
92         return lambda_ack.applyAsInt(1, Y1) + lambda_ack.applyAsInt(2, Y2) + lambda_ack.applyAsInt(3, Y3);
93     }
94 
95     public static final IntBinaryOperator mref_ack = AckermannI::mref_ack_helper;
96 
mref_ack_helper(int x, int y)97     public static int mref_ack_helper(int x, int y) {
98         return x == 0 ?
99                 y + 1 :
100                 (y == 0 ?
101                         mref_ack.applyAsInt(x - 1, 1) :
102                         mref_ack.applyAsInt(x - 1, mref_ack.applyAsInt(x, y - 1)));
103     }
104 
105     @Benchmark
106     @OperationsPerInvocation(9999999)
mref()107     public int mref() {
108         return mref_ack.applyAsInt(1, Y1) + mref_ack.applyAsInt(2, Y2) + mref_ack.applyAsInt(3, Y3);
109     }
110 
111 }
112 
113