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.compiler; 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.OutputTimeUnit; 29 import org.openjdk.jmh.annotations.Scope; 30 import org.openjdk.jmh.annotations.Setup; 31 import org.openjdk.jmh.annotations.State; 32 33 import java.util.Random; 34 import java.util.concurrent.TimeUnit; 35 36 /** 37 * Tests speed of division and remainder calculations. 38 */ 39 @BenchmarkMode(Mode.AverageTime) 40 @OutputTimeUnit(TimeUnit.NANOSECONDS) 41 @State(Scope.Thread) 42 public class DivRem { 43 44 private static final int ARRAYSIZE = 500; 45 46 /* instance fields for the constant int division tests. */ 47 public int[] intValues, intValues2; 48 49 /* instance fields for the constant long division tests. */ 50 public long[] longValues, longValues2; 51 52 /* instance fields for the tests using the testdr-method. */ 53 public long[] drLongValues1, drLongValues2; 54 55 public long[] drLongValuesAsInts1, drLongValuesAsInts2; 56 57 @Setup 58 public void setupSubclass() { 59 Random r = new Random(4711); 60 61 intValues = new int[ARRAYSIZE]; 62 intValues2 = new int[ARRAYSIZE]; 63 longValues = new long[ARRAYSIZE]; 64 longValues2 = new long[ARRAYSIZE]; 65 66 for (int i = 0; i < ARRAYSIZE; i++) { 67 intValues[i] = r.nextInt(); 68 if (intValues[i] == 0) { 69 intValues[i] = 5353; 70 } 71 intValues2[i] = r.nextInt(); 72 73 longValues[i] = r.nextLong(); 74 if (longValues[i] == 0) { 75 longValues[i] = 5353L; 76 } 77 longValues2[i] = r.nextLong(); 78 } 79 80 /* generate random longs for 32-64 tests */ 81 82 drLongValues1 = new long[ARRAYSIZE]; 83 drLongValues2 = new long[ARRAYSIZE]; 84 drLongValuesAsInts1 = new long[ARRAYSIZE]; 85 drLongValuesAsInts2 = new long[ARRAYSIZE]; 86 for (int i = 0; i < ARRAYSIZE; i++) { 87 long l = r.nextLong(); 88 if (l == 0L) { 89 l++; 90 } 91 drLongValues1[i] = l; 92 drLongValuesAsInts1[i] = (long) (int) l; 93 l = r.nextLong(); 94 if (l == 0L) { 95 l++; 96 } 97 drLongValues2[i] = l; 98 drLongValuesAsInts2[i] = (long) (int) l; 99 } 100 } 101 102 /** 103 * Tests integer division with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to 104 * a multiplication instead. 105 */ 106 @Benchmark 107 public int testIntDivConstantDivisor() { 108 int dummy = 0; 109 for (int i = 0; i < intValues.length; i++) { 110 dummy += intValues[i] / 49; 111 } 112 return dummy; 113 } 114 115 /** 116 * Tests long division with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to a 117 * multiplication instead. 118 */ 119 @Benchmark 120 public long testLongDivConstantDivisor() { 121 long dummy = 0; 122 for (int i = 0; i < longValues.length; i++) { 123 dummy += longValues[i] / 49L + longValues[i] / 0x4949494949L; 124 } 125 return dummy; 126 } 127 128 /** 129 * Tests integer remainder with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to 130 * two multiplications instead. 131 */ 132 @Benchmark 133 public int testIntRemConstantDivisor() { 134 int dummy = 0; 135 for (int i = 0; i < intValues.length; i++) { 136 dummy += intValues[i] % 49; 137 } 138 return dummy; 139 } 140 141 /** 142 * Tests long division with a constant divisor. Hopefully the JVM will do a Granlund-Montgomery and convert it to a 143 * multiplication instead. 144 */ 145 @Benchmark 146 public long testLongRemConstantDivisor() { 147 long dummy = 0; 148 for (int i = 0; i < longValues.length; i++) { 149 dummy += longValues[i] % 49L + longValues[i] % 0x4949494949L; 150 } 151 return dummy; 152 } 153 154 /** 155 * Tests integer division with a variable divisor. This benchmark is mainly here to be a comparison against the 156 * benchmark that performs both divisions and remainder calculations. 157 */ 158 @Benchmark 159 public int testIntDivVariableDivisor() { 160 int dummy = 0; 161 for (int i = 0; i < intValues.length; i++) { 162 dummy += intValues2[i] / intValues[i]; 163 } 164 return dummy; 165 } 166 167 /** 168 * Tests integer division and remainder with a variable divisor. Both calculations are performed with the same 169 * divisor, so a JVM should not have to perform two complex calculations. Either a division followed by a 170 * multiplication, or on X86 using idiv, where the reminder is also returned from the idiv instruction. 171 */ 172 @Benchmark 173 public int testIntDivRemVariableDivisor() { 174 int dummy = 0; 175 for (int i = 0; i < intValues.length; i++) { 176 dummy += intValues2[i] / intValues[i]; 177 dummy += intValues2[i] % intValues[i]; 178 } 179 return dummy; 180 } 181 182 @Benchmark 183 public long test64DivRem64() { 184 long dummy = 0; 185 for (int i = 0; i < drLongValues1.length; i++) { 186 long l1 = drLongValues1[i]; 187 long l2 = drLongValues2[i]; 188 dummy += l1 / l2; 189 dummy += l1 % l2; 190 } 191 return dummy; 192 } 193 194 @Benchmark 195 public long test32DivRem32() { 196 long dummy = 0; 197 for (int i = 0; i < drLongValuesAsInts1.length; i++) { 198 long l1 = drLongValuesAsInts1[i]; 199 long l2 = drLongValuesAsInts2[i]; 200 dummy += l1 / l2; 201 dummy += l1 % l2; 202 } 203 return dummy; 204 } 205 206 @Benchmark 207 public long test64DivRem32() { 208 long dummy = 0; 209 for (int i = 0; i < drLongValues1.length; i++) { 210 long l1 = drLongValues1[i]; 211 long l2 = drLongValuesAsInts2[i]; 212 dummy += l1 / l2; 213 dummy += l1 % l2; 214 } 215 return dummy; 216 } 217 }