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
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)
testConstructorWithString(Blackhole bh)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)
testConstructorWithDouble(Blackhole bh)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)
testToString(Blackhole bh)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)
testSetScale(Blackhole bh)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)
testSetScaleVarious(Blackhole bh)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)
testAdd(Blackhole bh)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)
testMultiply(Blackhole bh)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)
testCompareTo(Blackhole bh)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)
testHugeToString(Blackhole bh)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)
testLargeToString(Blackhole bh)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)
testSmallToString(Blackhole bh)221     public void testSmallToString(Blackhole bh) {
222         for (BigDecimal s : smallArray) {
223             bh.consume(s.toString());
224         }
225     }
226 }
227