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 
  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)
  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)
  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)
  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 
  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)
 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