Setup and TearDown executed by different threads

Dmitry Vyazelenko vyazelenko at yahoo.com
Wed Aug 13 11:06:00 UTC 2014


Hi,

I've found a problem in multi-threaded benchmarks that @Setup and
@TearDown are executed by different threads. This breaks the teardown
code, because it assumes that same thread that executed @Setup will 
execute @TearDown method.

Here is benchmark that illustrates the issue:
@Fork(1) 
@Warmup(iterations = 0) 
@Measurement(iterations = 1) 
@State(Scope.Benchmark) 
@BenchmarkMode(Mode.SingleShotTime) 
public class SetupAndTearDownBenchmarkScope { 
    private String trialThreadName; 
    private String iterationsThreadName; 
    private String invocationThreadName; 
    @Benchmark 
    public void baseline() { 
    } 
    private void printThread(String msg) { 
        System.out.println("\r\n[" + Thread.currentThread().getName() + "] => " + msg); 
    } 
    @Setup(Level.Trial) 
    public void setUpTrial() { 
        printThread("setUpTrial()"); 
    } 
    @TearDown(Level.Trial) 
    public void tearDownTrial() { 
        printThread("tearDownTrial()"); 
    } 
    @Setup(Level.Iteration) 
    public void setUpIteration() { 
        printThread("setUpIteration()"); 
    } 
    @TearDown(Level.Iteration) 
    public void tearDownIteration() { 
        printThread("tearDownIteration()"); 
    } 
    @Setup(Level.Invocation) 
    public void setUpInvocation() { 
        printThread("setUpInvocation()"); 
    } 
    @TearDown(Level.Invocation) 
    public void tearDownInvocation() { 
        printThread("tearDownInvocation()"); 
    } 
}

When I execute it using single thread (i.e. java -jar target\benchmarks.jar -t 1) I get:
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-1] => setUpTrial() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-1] => setUpIteration() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-1] => setUpInvocation() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-1] => tearDownInvocation() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-1] => tearDownIteration() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-1] => tearDownTrial()
Which basically confirms that same thread used for everything.

However with multiple threads (i.e. java -jar target\benchmarks.jar -t 4):
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-3] => setUpTrial() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-1] => setUpIteration() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-1] => setUpInvocation() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-1] => tearDownInvocation() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-3] => setUpInvocation() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-3] => tearDownInvocation() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-2] => setUpInvocation() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-2] => tearDownInvocation() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-2] => tearDownIteration() 
  [org.sample.SetupAndTearDownBenchmarkScope.baseline-jmh-worker-2] => tearDownTrial()

This clearly shows that setup/tearDown pairs are executed by different threads!

What I expect:
- For Scope.Benchmark single thread will execute all @Setup/@TearDown methods
(at least for Level.Trial and Level.Iteration, not sure about Level.Invocation though)
- For Scope.Thread each thread will execute it's own @Setup/@TearDown methods
- For Scope.Group probably use one of threads from the group? Or dedicated @Setup/@TrearDown
thread created in addition.

 
Best regards,
Dmitry


More information about the jmh-dev mailing list