Alex Averbuch Alex Averbuch - 4 months ago 19
Java Question

JMH: accessing BenchmarkParams from @Setup method of @State class

Is it possible to access

BenchmarkParams
in the
@Setup
of a
@State(Scope.Benchmark)
class, if that class is passed into a
@Benchmark
as parameter?


Minimal code example (actual usage is more complex, but this reproduces my issue):

@State( Scope.Benchmark )
public class Test
{
@Setup
public void setUp( BenchmarkParams params ){}

@Benchmark
public void nothing( Test test ){}
}


There is a basic JMH sample, but not where the
@State
is passed into a
@Benchmark
method

I'd like to access
BenchmarkParams
in
@Setup
to retrieve/log per-benchmark configuration data that I create based on JMH
@Param
values

With the sample code, above:


  1. Define
    @State(Scope.Benchmark)
    class named
    Test
    <--- works

  2. Define
    @Benchmark
    method named
    nothing()
    <--- works

  3. Pass
    @State
    instance into
    @Benchmark
    method <--- FAILS!



Here is the error:

[ERROR]
/Users/.../jmh-benchmarks/target/generated-sources/annotations/test/generated/Test_nothing_jmhTest.java:[390,16]
method setUp in class test.Test cannot be applied to given
types;
required: org.openjdk.jmh.infra.BenchmarkParams
found:
org.openjdk.jmh.infra.generated.BenchmarkParams_jmhType,org.openjdk.jmh.infra.generated.BenchmarkParams_jmhType
reason: actual and formal argument lists differ in length


Any help welcome!

[EDIT]

FYI, in my actual code there is also a
@State(Scope.Thread)
class, something more like:

@State( Scope.Benchmark )
public abstract class TestBase
{
@Setup
public void setUp( BenchmarkParams params ){}
}

@State( Scope.Benchmark )
public class TestImpl extends TestBase
{
@State( Scope.Thread )
public static class ThreadState
{
@Setup
public void setUp( TestImpl state ){}
}

@Benchmark
public void nothing( ThreadState state ){}
}

Answer

As explained in question, passing BenchmarkParams into @Setup of TestBasecauses JMH build failures

It seems to be related to having DAGs of @State classes

Passing BenchmarkParams into a @State(Scope.Benchmark) class that is not part of the "main" DAG (e.g., @State(Scope.Benchmark)->@State(Scope.Thread)->@Benchmark) branch seems to resolve that problem

For example,

@State( Scope.Benchmark )
public abstract class TestBase
{
    @Setup
    public void setUp( BenchmarkParamsState state )
    {
        // do something with state.someParam
    }

    @State( Scope.Benchmark )
    public static class BenchmarkParamsState
    {
        String someParam;

        @Setup
        public void setUp( BenchmarkParams params )
        {
            // set someParam based on contents of params
        }
    }
}

@State( Scope.Benchmark )
public class TestImpl extends TestBase
{
    @State( Scope.Thread )
    public static class ThreadState 
    {
        @Setup
        public void setUp( TestImpl state ){}
    }

    @Benchmark
    public void nothing( ThreadState state ){}
}

In addition, because BenchmarkParamsState is part of the greater DAG (due to being passed into @Setup of TestBase) its @Setup still occurs once for every @Benchmark

Comments