package com.bellsw.yield; import static java.util.concurrent.TimeUnit.*; import static org.openjdk.jmh.annotations.Mode.*; import static org.openjdk.jmh.annotations.Scope.*; import static org.openjdk.jmh.annotations.Level.*; import org.openjdk.jmh.infra.Control; import org.openjdk.jmh.annotations.*; @BenchmarkMode(Throughput) @Warmup(iterations = 5, time = 1, timeUnit = SECONDS) @Measurement(iterations = 5, time = 1, timeUnit = SECONDS)//, batchSize = 1000) @Fork(5) @OutputTimeUnit(MICROSECONDS) @State(Group) public class SpinWaitBench { @State(Scope.Thread) @AuxCounters(AuxCounters.Type.OPERATIONS) public static class Spins { public long totalSpins = 0; } public volatile long spinData; // even: ready to produce; odd: ready to consume; -3: terminate @Setup(Iteration) public void initSpins() { spinData = 0; } @Benchmark @Group("pong") @GroupThreads(1) public void produce(Control cnt, Spins aux) { long spins = 0; while ((spinData & 0x1) == 1 && !cnt.stopMeasurement) { // busy spin until ready to produce java.lang.Thread.onSpinWait(); spins++; } spinData++; // produce aux.totalSpins += spins; } @Benchmark @Group("pong") @GroupThreads(1) public void consume(Control cnt) { while ((spinData & 0x1) == 0 && !cnt.stopMeasurement) { // busy spin until ready to consume java.lang.Thread.onSpinWait(); } spinData++; // consume } }