1 /* 2 * Copyright (c) 2025, 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.valhalla.acmp.array; 24 25 import org.openjdk.jmh.annotations.Benchmark; 26 import org.openjdk.jmh.annotations.BenchmarkMode; 27 import org.openjdk.jmh.annotations.CompilerControl; 28 import org.openjdk.jmh.annotations.Fork; 29 import org.openjdk.jmh.annotations.Measurement; 30 import org.openjdk.jmh.annotations.Mode; 31 import org.openjdk.jmh.annotations.OperationsPerInvocation; 32 import org.openjdk.jmh.annotations.OutputTimeUnit; 33 import org.openjdk.jmh.annotations.Scope; 34 import org.openjdk.jmh.annotations.Setup; 35 import org.openjdk.jmh.annotations.State; 36 import org.openjdk.jmh.annotations.Warmup; 37 38 import java.util.BitSet; 39 import java.util.Random; 40 import java.util.concurrent.TimeUnit; 41 42 /* 43 * For proper results it should be executed: 44 * java -jar target/benchmarks.jar org.openjdk.bench.valhalla.acmp.array.Value -wmb "org.openjdk.bench.valhalla.acmp.array.Value.*050" 45 */ 46 47 @Fork(value = 3, jvmArgsAppend = {"--enable-preview"}) 48 @Warmup(iterations = 3, time = 1) 49 @Measurement(iterations = 5, time = 1) 50 @OutputTimeUnit(TimeUnit.NANOSECONDS) 51 @BenchmarkMode(Mode.AverageTime) 52 @State(Scope.Thread) 53 public class Value128 { 54 55 public static final int SIZE = 100; 56 57 @CompilerControl(CompilerControl.Mode.DONT_INLINE) 58 private static int cmp_branch_obj(Object[] objects1, Object[] objects2) { 59 int s = 0; 60 for (int i = 0; i < SIZE; i++) { 61 if (objects1[i] == objects2[i]) { 62 s += 1; 63 } else { 64 s -= 1; 65 } 66 } 67 return s; 68 } 69 70 @CompilerControl(CompilerControl.Mode.DONT_INLINE) 71 private static int cmp_branch_val(ValueInt4[] objects1, ValueInt4[] objects2) { 72 int s = 0; 73 for (int i = 0; i < SIZE; i++) { 74 if (objects1[i] == objects2[i]) { 75 s += 1; 76 } else { 77 s -= 1; 78 } 79 } 80 return s; 81 } 82 83 @CompilerControl(CompilerControl.Mode.DONT_INLINE) 84 private static boolean cmp_result_val(ValueInt4[] objects1, ValueInt4[] objects2) { 85 boolean s = false; 86 for (int i = 0; i < SIZE; i++) { 87 s ^= objects1[i] == objects2[i]; 88 } 89 return s; 90 } 91 92 @CompilerControl(CompilerControl.Mode.DONT_INLINE) 93 private static boolean cmp_result_obj(Object[] objects1, Object[] objects2) { 94 boolean s = false; 95 for (int i = 0; i < SIZE; i++) { 96 s ^= objects1[i] == objects2[i]; 97 } 98 return s; 99 } 100 101 @Benchmark 102 @OperationsPerInvocation(SIZE) 103 @CompilerControl(CompilerControl.Mode.INLINE) 104 public int branch_obj_equals000(ObjState00 st) { 105 return cmp_branch_obj(st.arr1, st.arr2); 106 } 107 108 @Benchmark 109 @OperationsPerInvocation(SIZE) 110 @CompilerControl(CompilerControl.Mode.INLINE) 111 public int branch_obj_equals025(ObjState25 st) { 112 return cmp_branch_obj(st.arr1, st.arr2); 113 } 114 115 @Benchmark 116 @OperationsPerInvocation(SIZE) 117 @CompilerControl(CompilerControl.Mode.INLINE) 118 public int branch_obj_equals050(ObjState50 st) { 119 return cmp_branch_obj(st.arr1, st.arr2); 120 } 121 122 @Benchmark 123 @OperationsPerInvocation(SIZE) 124 @CompilerControl(CompilerControl.Mode.INLINE) 125 public int branch_obj_equals075(ObjState75 st) { 126 return cmp_branch_obj(st.arr1, st.arr2); 127 } 128 129 @Benchmark 130 @OperationsPerInvocation(SIZE) 131 @CompilerControl(CompilerControl.Mode.INLINE) 132 public int branch_obj_equals100(ObjState100 st) { 133 return cmp_branch_obj(st.arr1, st.arr2); 134 } 135 136 @Benchmark 137 @OperationsPerInvocation(SIZE) 138 @CompilerControl(CompilerControl.Mode.INLINE) 139 public int branch_val_equals000(ValState00 st) { 140 return cmp_branch_val(st.arr1, st.arr2); 141 } 142 143 @Benchmark 144 @OperationsPerInvocation(SIZE) 145 @CompilerControl(CompilerControl.Mode.INLINE) 146 public int branch_val_equals025(ValState25 st) { 147 return cmp_branch_val(st.arr1, st.arr2); 148 } 149 150 @Benchmark 151 @OperationsPerInvocation(SIZE) 152 @CompilerControl(CompilerControl.Mode.INLINE) 153 public int branch_val_equals050(ValState50 st) { 154 return cmp_branch_val(st.arr1, st.arr2); 155 } 156 157 @Benchmark 158 @OperationsPerInvocation(SIZE) 159 @CompilerControl(CompilerControl.Mode.INLINE) 160 public int branch_val_equals075(ValState75 st) { 161 return cmp_branch_val(st.arr1, st.arr2); 162 } 163 164 @Benchmark 165 @OperationsPerInvocation(SIZE) 166 @CompilerControl(CompilerControl.Mode.INLINE) 167 public int branch_val_equals100(ValState100 st) { 168 return cmp_branch_val(st.arr1, st.arr2); 169 } 170 171 172 @Benchmark 173 @OperationsPerInvocation(SIZE) 174 @CompilerControl(CompilerControl.Mode.INLINE) 175 public boolean result_obj_equals000(ObjState00 st) { 176 return cmp_result_obj(st.arr1, st.arr2); 177 } 178 179 @Benchmark 180 @OperationsPerInvocation(SIZE) 181 @CompilerControl(CompilerControl.Mode.INLINE) 182 public boolean result_obj_equals025(ObjState25 st) { 183 return cmp_result_obj(st.arr1, st.arr2); 184 } 185 186 @Benchmark 187 @OperationsPerInvocation(SIZE) 188 @CompilerControl(CompilerControl.Mode.INLINE) 189 public boolean result_obj_equals050(ObjState50 st) { 190 return cmp_result_obj(st.arr1, st.arr2); 191 } 192 193 @Benchmark 194 @OperationsPerInvocation(SIZE) 195 @CompilerControl(CompilerControl.Mode.INLINE) 196 public boolean result_obj_equals075(ObjState75 st) { 197 return cmp_result_obj(st.arr1, st.arr2); 198 } 199 200 @Benchmark 201 @OperationsPerInvocation(SIZE) 202 @CompilerControl(CompilerControl.Mode.INLINE) 203 public boolean result_obj_equals100(ObjState100 st) { 204 return cmp_result_obj(st.arr1, st.arr2); 205 } 206 207 @Benchmark 208 @OperationsPerInvocation(SIZE) 209 @CompilerControl(CompilerControl.Mode.INLINE) 210 public boolean result_val_equals000(ValState00 st) { 211 return cmp_result_val(st.arr1, st.arr2); 212 } 213 214 @Benchmark 215 @OperationsPerInvocation(SIZE) 216 @CompilerControl(CompilerControl.Mode.INLINE) 217 public boolean result_val_equals025(ValState25 st) { 218 return cmp_result_val(st.arr1, st.arr2); 219 } 220 221 @Benchmark 222 @OperationsPerInvocation(SIZE) 223 @CompilerControl(CompilerControl.Mode.INLINE) 224 public boolean result_val_equals050(ValState50 st) { 225 return cmp_result_val(st.arr1, st.arr2); 226 } 227 228 @Benchmark 229 @OperationsPerInvocation(SIZE) 230 @CompilerControl(CompilerControl.Mode.INLINE) 231 public boolean result_val_equals075(ValState75 st) { 232 return cmp_result_val(st.arr1, st.arr2); 233 } 234 235 @Benchmark 236 @OperationsPerInvocation(SIZE) 237 @CompilerControl(CompilerControl.Mode.INLINE) 238 public boolean result_val_equals100(ValState100 st) { 239 return cmp_result_val(st.arr1, st.arr2); 240 } 241 242 public static value class ValueInt4 { 243 244 public final int v0; 245 public final int v1; 246 public final int v2; 247 public final int v3; 248 249 public ValueInt4(int v) { 250 this.v0 = v; 251 this.v1 = v + 1; 252 this.v2 = v + 2; 253 this.v3 = v + 3; 254 } 255 256 } 257 258 private static void populate(Object[] arr1, Object[] arr2, int eq) { 259 if (eq <= 0) { 260 arr1[0] = null; 261 arr2[0] = new ValueInt4(1); 262 arr1[1] = new ValueInt4(2); 263 arr2[1] = null; 264 for (int i = 2; i < SIZE; i++) { 265 arr1[i] = new ValueInt4(2 * i); 266 arr2[i] = new ValueInt4(2 * i + 1); 267 } 268 } else if (eq >= 100) { 269 arr2[0] = arr1[0] = null; 270 for (int i = 1; i < SIZE; i++) { 271 arr2[i] = arr1[i] = new ValueInt4(i); 272 } 273 } else { 274 BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); 275 boolean samenulls = true; 276 int distinctnulls = 0; 277 for (int i = 0; i < SIZE; i++) { 278 if (eqset.get(i)) { 279 if(samenulls) { 280 arr2[i] = arr1[i] = null; 281 samenulls = false; 282 } else { 283 arr2[i] = arr1[i] = new ValueInt4(i); 284 } 285 } else { 286 switch (distinctnulls) { 287 case 0: 288 arr1[i] = null; 289 arr2[i] = new ValueInt4(2 * i + 1); 290 distinctnulls = 1; 291 break; 292 case 1: 293 arr1[i] = new ValueInt4(2 * i); 294 arr2[i] = null; 295 distinctnulls = 2; 296 break; 297 default: 298 arr1[i] = new ValueInt4(2 * i); 299 arr2[i] = new ValueInt4(2 * i + 1); 300 break; 301 } 302 } 303 } 304 305 } 306 } 307 308 @State(Scope.Thread) 309 public abstract static class ObjState { 310 Object[] arr1, arr2; 311 312 public void setup(int eq) { 313 arr1 = new Object[SIZE]; 314 arr2 = new Object[SIZE]; 315 populate(arr1, arr2, eq); 316 } 317 } 318 319 @State(Scope.Thread) 320 public abstract static class ValState { 321 ValueInt4[] arr1, arr2; 322 323 public void setup(int eq) { 324 arr1 = new ValueInt4[SIZE]; 325 arr2 = new ValueInt4[SIZE]; 326 populate(arr1, arr2, eq); 327 } 328 } 329 330 public static class ObjState00 extends ObjState { 331 @Setup 332 public void setup() { 333 setup(0); 334 } 335 } 336 337 public static class ObjState25 extends ObjState { 338 @Setup 339 public void setup() { 340 setup(25); 341 } 342 } 343 344 public static class ObjState50 extends ObjState { 345 @Setup 346 public void setup() { 347 setup(50); 348 } 349 } 350 351 public static class ObjState75 extends ObjState { 352 @Setup 353 public void setup() { 354 setup(75); 355 } 356 } 357 358 public static class ObjState100 extends ObjState { 359 @Setup 360 public void setup() { 361 setup(100); 362 } 363 } 364 365 public static class ValState00 extends ValState { 366 @Setup 367 public void setup() { 368 setup(0); 369 } 370 } 371 372 public static class ValState25 extends ValState { 373 @Setup 374 public void setup() { 375 setup(25); 376 } 377 } 378 379 public static class ValState50 extends ValState { 380 @Setup 381 public void setup() { 382 setup(50); 383 } 384 } 385 386 public static class ValState75 extends ValState { 387 @Setup 388 public void setup() { 389 setup(75); 390 } 391 } 392 393 public static class ValState100 extends ValState { 394 @Setup 395 public void setup() { 396 setup(100); 397 } 398 } 399 400 }