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