RFR (S) : JDK-8245043 : Simplified contention benchmark

eric.caspole at oracle.com eric.caspole at oracle.com
Wed Jun 3 15:25:18 UTC 2020


Hi Aleksey,
Thanks for your comments! I simplified the whole thing while still 
getting the behavior and profiles I am looking for, that is, all the 
recursive locking and throwing can make this micro spend several percent 
in the Hotspot C++ locking code in enter/exit/inflate etc. So the point 
of this is to make a relatively easy way to exercise the locking code by 
setting the parameters as needed.

Here is the new version:

http://cr.openjdk.java.net/~ecaspole/JDK-8245043/02/webrev/

Regards,
Eric

On 5/20/20 3:45 PM, Aleksey Shipilev wrote:
> On 5/18/20 10:33 PM, eric.caspole at oracle.com wrote:
>> Webrev:
>> http://cr.openjdk.java.net/~ecaspole/JDK-8245043/01/webrev/
> 
> I firmly believe the goal for microbenchmarks is to avoid accidental complexity.
> 
> Minimize the whole thing:
>    *) No need for two @State-s, to have one carry @Param-s only -- you might as well use a single
> state, and initialize @Param-s there. For this workload, it would mean you can just mark the entire
> class the single state, and that simplifies the code;
>    *) update(...), update1(...), update2(...) have single calls, you can inline them?
>    *) refreshArray(...) is only used from setup(), you can inline it?
>    *) Session/Table are probably redundant; I guess the only way it might matter is bulk rebias;
>    *) sharedLocks need not be volatile, @Setup does all we want already.
>    *) I cannot see why "while (waiter == null)" is needed; we always get the lock?
> 
> Other issues:
>    *) static "random" is probably a scalability bottleneck that hides some locking behavior;
>    *) Not sure if recurrent locking in update -> update1 -> update2 is meaningful;
> 
> Seems to me, this whole thing boils down to much more understandable (untested!):
> 
> @State(Scope.Thread)
> @BenchmarkMode(Mode.Throughput)
> @OutputTimeUnit(TimeUnit.MILLISECONDS)
> @Threads(Threads.MAX)
> public class MonitorBench {
> 
>      @Param({"20", "100", "250"})
>      int consumeUnlocked;
> 
>      @Param({"20", "100", "250"})
>      int consumeLocked;
> 
>      @Param({"1", "2", "4"})
>      int throwThreshold;
> 
>      @Param({"10000"})
>      int range;
> 
>      @Param({"1"})
>      int locksSize;
> 
>      static final Random R = new Random(115655);
> 
>      Object perThreadLock;
>      Object[] sharedLocks;
> 
>      int threadCompute;
>      int sharedLockIndex;
> 
>      @Setup
>      public void setup() {
>          threadCompute = R.nextInt(Runtime.getRuntime().availableProcessors());
>          sharedLockIndex = R.nextInt(locksSize);
>          perThreadLock = new Object();
> 
>          sharedLocks = new Object[locksSize];
>          for (int i = 0; i < locksSize; i++) {
>              sharedLocks[i] = new Object();
>          }
>      }
> 
>      @Benchmark
>      public int action() throws InterruptedException {
>          synchronized (perThreadLock) {
>              Blackhole.consumeCPU(consumeUnlocked + threadCompute);
> 
>              Object waiter = sharedLocks[sharedLockIndex];
>              synchronized (waiter) {
>                  while (true) {
>                      Blackhole.consumeCPU(consumeLocked);
>                      if (R.nextInt(range) < throwThreshold) {
>                          waiter.wait(100);
>                      } else {
>                          Blackhole.consumeCPU(consumeLocked);
>                          return 0;
>                      }
>                  }
>              }
>          }
>      }
> }
> 
> 


More information about the hotspot-runtime-dev mailing list