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.java.math;
  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 import org.openjdk.jmh.annotations.Scope;
  31 import org.openjdk.jmh.annotations.Setup;
  32 import org.openjdk.jmh.annotations.State;
  33 import org.openjdk.jmh.infra.Blackhole;
  34 
  35 import java.math.BigDecimal;
  36 import java.util.Random;
  37 import java.util.concurrent.TimeUnit;
  38 
  39 @BenchmarkMode(Mode.AverageTime)
  40 @OutputTimeUnit(TimeUnit.NANOSECONDS)
  41 @State(Scope.Thread)
  42 public class BigDecimals {
  43 
  44     /** Make sure TEST_SIZE is used to size the arrays. We need this constant to parametrize the operations count. */
  45     private static final int TEST_SIZE = 100;
  46 
  47     /* dummy variables for intermediate results */
  48     public Object[] dummyArr;
  49     public String[] dummyStringArray;
  50     public int dummy;
  51 
  52     /* array to hold the created objects. */
  53     private BigDecimal[] bigDecimals;
  54     private String[] stringInputs;
  55     private double[] doubleInputs;
  56     private BigDecimal[] hugeArray, largeArray, smallArray;
  57 
  58     @Setup
  59     public void setup() {
  60         Random r = new Random(1123);
  61         dummyArr = new Object[TEST_SIZE];
  62         bigDecimals = new BigDecimal[TEST_SIZE];
  63         stringInputs = new String[TEST_SIZE];
  64         doubleInputs = new double[TEST_SIZE];
  65         for (int i = 0; i < TEST_SIZE; i++) {
  66             double value = (double) (i + 1);
  67             switch (i % 4) {
  68                 case 0:
  69                     value = -value * 54345.0d;
  70                     break;
  71                 case 1:
  72                     value = value * 5434543453454355e100;
  73                     break;
  74                 case 2:
  75                     value = -value / 5434543453454355e100;
  76                     break;
  77                 case 3:
  78                     break;
  79             }
  80 
  81             bigDecimals[i] = new BigDecimal(value);
  82             stringInputs[i] = "" + value;
  83             doubleInputs[i] = value;
  84         }
  85 
  86         /*
  87          * Huge numbers larger than MAX_LONG
  88          */
  89         hugeArray = new BigDecimal[TEST_SIZE];
  90 
  91         /*
  92         * Large numbers less than MAX_LONG but larger than MAX_INT
  93         */
  94         largeArray = new BigDecimal[TEST_SIZE];
  95 
  96         /*
  97         * Small number less than MAX_INT
  98         */
  99         smallArray = new BigDecimal[TEST_SIZE];
 100 
 101         dummyStringArray = new String[TEST_SIZE];
 102         for (int i = 0; i < TEST_SIZE; i++) {
 103             int value = Math.abs(r.nextInt());
 104             hugeArray[i] = new BigDecimal("" + ((long) value + (long) Integer.MAX_VALUE)
 105                     + ((long) value + (long) Integer.MAX_VALUE) + ".55");
 106             largeArray[i] = new BigDecimal("" + ((long) value + (long) Integer.MAX_VALUE) + ".55");
 107             smallArray[i] = new BigDecimal("" + ((long) value / 1000) + ".55");
 108         }
 109     }
 110 
 111     /** Invokes the (String)-constructor of BigDecimal with various different values. */
 112     @Benchmark
 113     @OperationsPerInvocation(TEST_SIZE)
 114     public void testConstructorWithString(Blackhole bh) {
 115         for (String s : stringInputs) {
 116             bh.consume(new BigDecimal(s));
 117         }
 118     }
 119 
 120     /** Invokes the (double)-constructor of BigDecimal with various different values. */
 121     @Benchmark
 122     @OperationsPerInvocation(TEST_SIZE)
 123     public void testConstructorWithDouble(Blackhole bh) {
 124         for (double s : doubleInputs) {
 125             bh.consume(new BigDecimal(s));
 126         }
 127     }
 128 
 129     /** Invokes the toString method of BigDecimal with various different values. */
 130     @Benchmark
 131     @OperationsPerInvocation(TEST_SIZE)
 132     public void testToString(Blackhole bh) {
 133         for (BigDecimal s : bigDecimals) {
 134             bh.consume(s.toString());
 135         }
 136     }
 137 
 138     /**
 139      * Invokes the setScale method of BigDecimal with various different values.
 140      */
 141     @Benchmark
 142     @OperationsPerInvocation(TEST_SIZE)
 143     public void testSetScale(Blackhole bh) {
 144         for (BigDecimal s : bigDecimals) {
 145             bh.consume(s.setScale(2, BigDecimal.ROUND_HALF_UP));
 146         }
 147     }
 148 
 149     /** Invokes the setScale method of BigDecimal with various different values. */
 150     @Benchmark
 151     @OperationsPerInvocation(50 * TEST_SIZE)
 152     public void testSetScaleVarious(Blackhole bh) {
 153         for (int scale = 0; scale < 50; scale++) {
 154             for (BigDecimal s : bigDecimals) {
 155                 bh.consume(s.setScale(scale, BigDecimal.ROUND_HALF_UP));
 156             }
 157         }
 158     }
 159 
 160     /** Invokes the add method of BigDecimal with various different values. */
 161     @Benchmark
 162     @OperationsPerInvocation(TEST_SIZE)
 163     public void testAdd(Blackhole bh) {
 164         BigDecimal tmp = null;
 165         for (BigDecimal s : bigDecimals) {
 166             if (tmp == null) {
 167                 tmp = s;
 168                 continue;
 169             }
 170             tmp = tmp.add(s);
 171         }
 172         bh.consume(tmp);
 173     }
 174 
 175     /** Invokes the multiply method of BigDecimal with various different values. */
 176     @Benchmark
 177     @OperationsPerInvocation(TEST_SIZE)
 178     public void testMultiply(Blackhole bh) {
 179         BigDecimal tmp = null;
 180         for (BigDecimal s : bigDecimals) {
 181             if (tmp == null) {
 182                 tmp = s;
 183                 continue;
 184             }
 185             tmp = tmp.multiply(s);
 186         }
 187         bh.consume(tmp);
 188     }
 189 
 190     /** Invokes the compareTo method of BigDecimal with various different values. */
 191     @Benchmark
 192     @OperationsPerInvocation(TEST_SIZE - 1)
 193     public void testCompareTo(Blackhole bh) {
 194         BigDecimal c = bigDecimals[0];
 195         for (BigDecimal s : bigDecimals) {
 196             bh.consume(c.compareTo(s));
 197         }
 198     }
 199 
 200     /** Test BigDecimal.toString() with huge numbers larger than MAX_LONG */
 201     @Benchmark
 202     @OperationsPerInvocation(TEST_SIZE)
 203     public void testHugeToString(Blackhole bh) {
 204         for (BigDecimal s : hugeArray) {
 205             bh.consume(s.toString());
 206         }
 207     }
 208 
 209     /** Test BigDecimal.toString() with large numbers less than MAX_LONG but larger than MAX_INT */
 210     @Benchmark
 211     @OperationsPerInvocation(TEST_SIZE)
 212     public void testLargeToString(Blackhole bh) {
 213         for (BigDecimal s : largeArray) {
 214             bh.consume(s.toString());
 215         }
 216     }
 217 
 218     /** Test BigDecimal.toString() with small numbers less than MAX_INT */
 219     @Benchmark
 220     @OperationsPerInvocation(TEST_SIZE)
 221     public void testSmallToString(Blackhole bh) {
 222         for (BigDecimal s : smallArray) {
 223             bh.consume(s.toString());
 224         }
 225     }
 226 }