1 /* 2 * Copyright (c) 2014, 2021, 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.lang; 24 25 import org.openjdk.jmh.annotations.Benchmark; 26 import org.openjdk.jmh.annotations.BenchmarkMode; 27 import org.openjdk.jmh.annotations.Fork; 28 import org.openjdk.jmh.annotations.Measurement; 29 import org.openjdk.jmh.annotations.Mode; 30 import org.openjdk.jmh.annotations.OutputTimeUnit; 31 import org.openjdk.jmh.annotations.Param; 32 import org.openjdk.jmh.annotations.Scope; 33 import org.openjdk.jmh.annotations.Setup; 34 import org.openjdk.jmh.annotations.State; 35 import org.openjdk.jmh.annotations.Threads; 36 import org.openjdk.jmh.annotations.Warmup; 37 38 import java.util.concurrent.TimeUnit; 39 40 41 /** 42 * Benchmark class for simple lock unlock tests. Nothing big should ever go into this class. 43 */ 44 @BenchmarkMode(Mode.AverageTime) 45 @OutputTimeUnit(TimeUnit.NANOSECONDS) 46 @State(Scope.Benchmark) 47 @Warmup(iterations = 4, time = 2) 48 @Measurement(iterations = 4, time = 2) 49 @Fork(value = 3) 50 public class LockUnlock { 51 52 @Param("100") 53 private int innerCount; 54 55 public Object lockObject1; 56 public Object lockObject2; 57 public volatile Object lockObject3Inflated; 58 public volatile Object lockObject4Inflated; 59 public int factorial; 60 public int dummyInt1; 61 public int dummyInt2; 62 63 @Setup 64 public void setup() { 65 lockObject1 = new Object(); 66 lockObject2 = new Object(); 67 lockObject3Inflated = new Object(); 68 lockObject4Inflated = new Object(); 69 70 // Inflate the lock to use an ObjectMonitor 71 try { 72 synchronized (lockObject3Inflated) { 73 lockObject3Inflated.wait(1); 74 } 75 synchronized (lockObject4Inflated) { 76 lockObject4Inflated.wait(1); 77 } 78 } catch (InterruptedException e) { 79 throw new RuntimeException(e); 80 } 81 82 dummyInt1 = 47; 83 dummyInt2 = 11; // anything 84 } 85 86 /** Perform a synchronized on a local object within a loop. */ 87 @Benchmark 88 public void testBasicSimpleLockUnlockLocal() { 89 Object localObject = lockObject1; 90 for (int i = 0; i < innerCount; i++) { 91 synchronized (localObject) { 92 dummyInt1++; 93 dummyInt2++; 94 } 95 } 96 } 97 98 /** Perform a synchronized on an object within a loop. */ 99 @Benchmark 100 public void testBasicSimpleLockUnlock() { 101 for (int i = 0; i < innerCount; i++) { 102 synchronized (lockObject1) { 103 dummyInt1++; 104 dummyInt2++; 105 } 106 } 107 } 108 109 /** Perform a synchronized on a local object within a loop. */ 110 @Benchmark 111 public void testInflatedSimpleLockUnlockLocal() { 112 Object localObject = lockObject3Inflated; 113 for (int i = 0; i < innerCount; i++) { 114 synchronized (localObject) { 115 dummyInt1++; 116 dummyInt2++; 117 } 118 } 119 } 120 121 /** Perform a synchronized on an object within a loop. */ 122 @Benchmark 123 public void testInflatedSimpleLockUnlock() { 124 for (int i = 0; i < innerCount; i++) { 125 synchronized (lockObject3Inflated) { 126 dummyInt1++; 127 dummyInt2++; 128 } 129 } 130 } 131 132 /** Perform a recursive synchronized on a local object within a loop. */ 133 @Benchmark 134 public void testBasicRecursiveLockUnlockLocal() { 135 Object localObject = lockObject1; 136 for (int i = 0; i < innerCount; i++) { 137 synchronized (localObject) { 138 synchronized (localObject) { 139 dummyInt1++; 140 dummyInt2++; 141 } 142 } 143 } 144 } 145 146 /** Perform a recursive synchronized on an object within a loop. */ 147 @Benchmark 148 public void testBasicRecursiveLockUnlock() { 149 for (int i = 0; i < innerCount; i++) { 150 synchronized (lockObject1) { 151 synchronized (lockObject1) { 152 dummyInt1++; 153 dummyInt2++; 154 } 155 } 156 } 157 } 158 159 /** Perform two synchronized after each other on the same local object. */ 160 @Benchmark 161 public void testBasicSerialLockUnlockLocal() { 162 Object localObject = lockObject1; 163 for (int i = 0; i < innerCount; i++) { 164 synchronized (localObject) { 165 dummyInt1++; 166 } 167 synchronized (localObject) { 168 dummyInt2++; 169 } 170 } 171 } 172 173 /** Perform two synchronized after each other on the same object. */ 174 @Benchmark 175 public void testBasicSerialLockUnlock() { 176 for (int i = 0; i < innerCount; i++) { 177 synchronized (lockObject1) { 178 dummyInt1++; 179 } 180 synchronized (lockObject1) { 181 dummyInt2++; 182 } 183 } 184 } 185 186 /** Perform two synchronized after each other on the same local object. */ 187 @Benchmark 188 public void testInflatedSerialLockUnlockLocal() { 189 Object localObject = lockObject3Inflated; 190 for (int i = 0; i < innerCount; i++) { 191 synchronized (localObject) { 192 dummyInt1++; 193 } 194 synchronized (localObject) { 195 dummyInt2++; 196 } 197 } 198 } 199 200 /** Perform two synchronized after each other on the same object. */ 201 @Benchmark 202 public void testInflatedSerialLockUnlock() { 203 for (int i = 0; i < innerCount; i++) { 204 synchronized (lockObject3Inflated) { 205 dummyInt1++; 206 } 207 synchronized (lockObject3Inflated) { 208 dummyInt2++; 209 } 210 } 211 } 212 213 /** Perform two synchronized after each other on the same object. */ 214 @Benchmark 215 public void testInflatedMultipleSerialLockUnlock() { 216 for (int i = 0; i < innerCount; i++) { 217 synchronized (lockObject3Inflated) { 218 dummyInt1++; 219 } 220 synchronized (lockObject4Inflated) { 221 dummyInt2++; 222 } 223 } 224 } 225 226 /** Perform two synchronized after each other on the same object. */ 227 @Benchmark 228 public void testInflatedMultipleRecursiveLockUnlock() { 229 for (int i = 0; i < innerCount; i++) { 230 synchronized (lockObject3Inflated) { 231 dummyInt1++; 232 synchronized (lockObject4Inflated) { 233 dummyInt2++; 234 } 235 } 236 } 237 } 238 239 /** Perform a recursive-only synchronized on a local object within a loop. */ 240 @Benchmark 241 public void testInflatedRecursiveOnlyLockUnlockLocal() { 242 Object localObject = lockObject3Inflated; 243 synchronized (localObject) { 244 for (int i = 0; i < innerCount; i++) { 245 synchronized (localObject) { 246 dummyInt1++; 247 dummyInt2++; 248 } 249 } 250 } 251 } 252 253 /** Perform a recursive-only synchronized on an object within a loop. */ 254 @Benchmark 255 public void testInflatedRecursiveOnlyLockUnlock() { 256 synchronized (lockObject3Inflated) { 257 for (int i = 0; i < innerCount; i++) { 258 synchronized (lockObject3Inflated) { 259 dummyInt1++; 260 dummyInt2++; 261 } 262 } 263 } 264 } 265 266 /** Perform a recursive-only synchronized on a local object within a loop. */ 267 @Benchmark 268 public void testInflatedRecursiveLockUnlockLocal() { 269 Object localObject = lockObject3Inflated; 270 for (int i = 0; i < innerCount; i++) { 271 synchronized (localObject) { 272 synchronized (localObject) { 273 dummyInt1++; 274 dummyInt2++; 275 } 276 } 277 } 278 } 279 280 /** Perform a recursive-only synchronized on an object within a loop. */ 281 @Benchmark 282 public void testInflatedRecursiveLockUnlock() { 283 for (int i = 0; i < innerCount; i++) { 284 synchronized (lockObject3Inflated) { 285 synchronized (lockObject3Inflated) { 286 dummyInt1++; 287 dummyInt2++; 288 } 289 } 290 } 291 } 292 293 /** 294 * Performs recursive synchronizations on the same local object. 295 * <p/> 296 * Result is 3628800 297 */ 298 @Benchmark 299 public void testRecursiveSynchronization() { 300 factorial = fact(10); 301 } 302 303 private synchronized int fact(int n) { 304 if (n == 0) { 305 return 1; 306 } else { 307 return fact(n - 1) * n; 308 } 309 } 310 311 /** 312 * With two threads lockObject1 will be contended so should be 313 * inflated. 314 */ 315 @Threads(2) 316 @Benchmark 317 public void testContendedLock() { 318 synchronized (lockObject1) { 319 dummyInt1++; 320 } 321 } 322 }