Scope.Thread and @Setup bug?

Aleksey Shipilev shade at redhat.com
Wed Sep 28 07:20:47 UTC 2016


On 09/27/2016 08:19 PM, Lev Serebryakov wrote:
> On 27.09.2016 15:54, Aleksey Shipilev wrote:
> 
>> It can even initialize after the shared @State(Benchmark) object:
>> http://hg.openjdk.java.net/code-tools/jmh/file/e810ce09937a/jmh-samples/src/main/java/org/openjdk/jmh/samples/JMHSample_29_StatesDAG.java
> 
>  Hmmm, I wrote this [code at the end of the message] and sometimes I got
> exception from my setup method, that shows that it was called twice. My
> ".registerReader()" and ".registerWriter()" checks, that they was called
> only once, and sometimes it is not the case and my invariant check

With @State(Scope.Thread), @Setup method would be called once by *each
thread* that has a reference to a state object. Is that what you are
seeing? If you have multiple threads calling e.g. writer(), then every
one will have its own thread-local instance of {Reader,Writer}State, and
try to register in your buf.

Anyhow, would be nice to see the MCVE example of the failure, because my
quick test does not fail:

@Fork(1)
@Warmup(iterations = 5, time = 5)
@Measurement(iterations = 10, time = 5)
@State(Scope.Group)
@Timeout(time = 5)
public class GroupThreadTimesTest {
    @State(Scope.Group)
    public static class GroupState {
        static boolean visited;

        @Setup
        public synchronized void setup() {
            if (visited) {
                throw new IllegalStateException("Already visited!");
            }
            visited = true;
        }
    }

    @State(Scope.Thread)
    public static class ReaderState {
        static final Set<Thread> threads =
                Collections.newSetFromMap(new ConcurrentHashMap<Thread,
Boolean>());

        @Setup
        public void setup(GroupState gs) {
            if (!threads.add(Thread.currentThread())) {
                throw new IllegalStateException("Already visited by " +
                        Thread.currentThread());
            }
        }
    }

    @State(Scope.Thread)
    public static class WriterState {
        static final Set<Thread> threads =
                Collections.newSetFromMap(new ConcurrentHashMap<Thread,
Boolean>());

        @Setup
        public void setup(GroupState gs) {
            if (!threads.add(Thread.currentThread())) {
                throw new IllegalStateException("Already visited by " +
                        Thread.currentThread());
            }
        }
    }

    @Benchmark
    @Group("buf")
    public void writer(WriterState s) throws InterruptedException {
        // Write to buffer
    }

    @Benchmark
    @Group("buf")
    public void reader(ReaderState s) throws InterruptedException {
        // Read from buffer
    }

}


Thanks,
-Aleksey



More information about the jmh-dev mailing list