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.field; 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.field.Value -wmb "org.openjdk.bench.valhalla.acmp.field.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 Value032 { 54 55 public static final int SIZE = 100; 56 57 @CompilerControl(CompilerControl.Mode.DONT_INLINE) 58 private static int cmp_branch_obj(ObjWrapper[] objects1, ObjWrapper[] objects2) { 59 int s = 0; 60 for (int i = 0; i < SIZE; i++) { 61 if (objects1[i].f == objects2[i].f) { 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(ValWrapper[] objects1, ValWrapper[] objects2) { 72 int s = 0; 73 for (int i = 0; i < SIZE; i++) { 74 if (objects1[i].f == objects2[i].f) { 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(ValWrapper[] objects1, ValWrapper[] objects2) { 85 boolean s = false; 86 for (int i = 0; i < SIZE; i++) { 87 s ^= objects1[i].f == objects2[i].f; 88 } 89 return s; 90 } 91 92 @CompilerControl(CompilerControl.Mode.DONT_INLINE) 93 private static boolean cmp_result_obj(ObjWrapper[] objects1, ObjWrapper[] objects2) { 94 boolean s = false; 95 for (int i = 0; i < SIZE; i++) { 96 s ^= objects1[i].f == objects2[i].f; 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 ValueInt { 243 244 public final int v0; 245 246 public ValueInt(int v0) { 247 this.v0 = v0; 248 } 249 250 public int value() { 251 return v0; 252 } 253 254 } 255 256 private static void populate(ObjWrapper[] arr1, ObjWrapper[] arr2, int eq) { 257 if (eq <= 0) { 258 arr1[0] = new ObjWrapper(null); 259 arr2[0] = new ObjWrapper(new ValueInt(1)); 260 arr1[1] = new ObjWrapper(new ValueInt(2)); 261 arr2[1] = new ObjWrapper(null); 262 for (int i = 2; i < SIZE; i++) { 263 arr1[i] = new ObjWrapper(new ValueInt(2 * i)); 264 arr2[i] = new ObjWrapper(new ValueInt(2 * i + 1)); 265 } 266 } else if (eq >= 100) { 267 arr2[0] = arr1[0] = new ObjWrapper(null); 268 for (int i = 1; i < SIZE; i++) { 269 ValueInt x = new ValueInt(i); 270 arr2[i] = new ObjWrapper(x); 271 arr1[i] = new ObjWrapper(x); 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] = new ObjWrapper(null); 281 arr1[i] = new ObjWrapper(null); 282 samenulls = false; 283 } else { 284 ValueInt x = new ValueInt(i); 285 arr2[i] = new ObjWrapper(x); 286 arr1[i] = new ObjWrapper(x); 287 } 288 } else { 289 switch (distinctnulls) { 290 case 0: 291 arr1[i] = new ObjWrapper(null); 292 arr2[i] = new ObjWrapper(new ValueInt(2 * i + 1)); 293 distinctnulls = 1; 294 break; 295 case 1: 296 arr1[i] = new ObjWrapper(new ValueInt(2 * i)); 297 arr2[i] = new ObjWrapper(null); 298 distinctnulls = 2; 299 break; 300 default: 301 arr1[i] = new ObjWrapper(new ValueInt(2 * i)); 302 arr2[i] = new ObjWrapper(new ValueInt(2 * i + 1)); 303 break; 304 } 305 } 306 } 307 } 308 } 309 310 311 private static void populate(ValWrapper[] arr1, ValWrapper[] arr2, int eq) { 312 if (eq <= 0) { 313 arr1[0] = new ValWrapper(null); 314 arr2[0] = new ValWrapper(new ValueInt(1)); 315 arr1[1] = new ValWrapper(new ValueInt(2)); 316 arr2[1] = new ValWrapper(null); 317 for (int i = 2; i < SIZE; i++) { 318 arr1[i] = new ValWrapper(new ValueInt(2 * i)); 319 arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); 320 } 321 } else if (eq >= 100) { 322 arr2[0] = arr1[0] = new ValWrapper(null); 323 for (int i = 1; i < SIZE; i++) { 324 ValueInt x = new ValueInt(i); 325 arr2[i] = new ValWrapper(x); 326 arr1[i] = new ValWrapper(x); 327 } 328 } else { 329 BitSet eqset = new Random(42).ints(0, SIZE).distinct().limit(eq * SIZE / 100).collect(BitSet::new, BitSet::set, BitSet::or); 330 boolean samenulls = true; 331 int distinctnulls = 0; 332 for (int i = 0; i < SIZE; i++) { 333 if (eqset.get(i)) { 334 if(samenulls) { 335 arr2[i] = new ValWrapper(null); 336 arr1[i] = new ValWrapper(null); 337 samenulls = false; 338 } else { 339 ValueInt x = new ValueInt(i); 340 arr2[i] = new ValWrapper(x); 341 arr1[i] = new ValWrapper(x); 342 } 343 } else { 344 switch (distinctnulls) { 345 case 0: 346 arr1[i] = new ValWrapper(null); 347 arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); 348 distinctnulls = 1; 349 break; 350 case 1: 351 arr1[i] = new ValWrapper(new ValueInt(2 * i)); 352 arr2[i] = new ValWrapper(null); 353 distinctnulls = 2; 354 break; 355 default: 356 arr1[i] = new ValWrapper(new ValueInt(2 * i)); 357 arr2[i] = new ValWrapper(new ValueInt(2 * i + 1)); 358 break; 359 } 360 } 361 } 362 } 363 } 364 365 public static class ObjWrapper { 366 public Object f; 367 368 public ObjWrapper(Object f) { 369 this.f = f; 370 } 371 } 372 373 public static class ValWrapper { 374 public ValueInt f; 375 376 public ValWrapper(ValueInt f) { 377 this.f = f; 378 } 379 } 380 381 @State(Scope.Thread) 382 public abstract static class ObjState { 383 ObjWrapper[] arr1, arr2; 384 385 public void setup(int eq) { 386 arr1 = new ObjWrapper[SIZE]; 387 arr2 = new ObjWrapper[SIZE]; 388 populate(arr1, arr2, eq); 389 } 390 } 391 392 @State(Scope.Thread) 393 public abstract static class ValState { 394 ValWrapper[] arr1, arr2; 395 396 public void setup(int eq) { 397 arr1 = new ValWrapper[SIZE]; 398 arr2 = new ValWrapper[SIZE]; 399 populate(arr1, arr2, eq); 400 } 401 } 402 403 public static class ObjState00 extends ObjState { 404 @Setup 405 public void setup() { 406 setup(0); 407 } 408 } 409 410 public static class ObjState25 extends ObjState { 411 @Setup 412 public void setup() { 413 setup(25); 414 } 415 } 416 417 public static class ObjState50 extends ObjState { 418 @Setup 419 public void setup() { 420 setup(50); 421 } 422 } 423 424 public static class ObjState75 extends ObjState { 425 @Setup 426 public void setup() { 427 setup(75); 428 } 429 } 430 431 public static class ObjState100 extends ObjState { 432 @Setup 433 public void setup() { 434 setup(100); 435 } 436 } 437 438 public static class ValState00 extends ValState { 439 @Setup 440 public void setup() { 441 setup(0); 442 } 443 } 444 445 public static class ValState25 extends ValState { 446 @Setup 447 public void setup() { 448 setup(25); 449 } 450 } 451 452 public static class ValState50 extends ValState { 453 @Setup 454 public void setup() { 455 setup(50); 456 } 457 } 458 459 public static class ValState75 extends ValState { 460 @Setup 461 public void setup() { 462 setup(75); 463 } 464 } 465 466 public static class ValState100 extends ValState { 467 @Setup 468 public void setup() { 469 setup(100); 470 } 471 } 472 473 }