RFR (S) : JDK-8245043 : Simplified contention benchmark
Aleksey Shipilev
shade at redhat.com
Wed May 20 19:45:42 UTC 2020
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;
}
}
}
}
}
}
--
Thanks,
-Aleksey
More information about the hotspot-runtime-dev
mailing list