6

jmh( http://openjdk.java.net/projects/code-tools/jmh/ ) を使用して、いくつかのメソッドのベンチマークを行います。また、このメソッドを実行するための引数として使用するパラメーターのセットもあります。特定のパラメーター値ごとにメソッドを生成することは可能ですか (@GenerateMicroBenchmark アノテーションを使用)?

今、私は同様の実装を使用していますが、手作業で多くの統一されたコードを書かなければならないため、あまり便利ではありません:

interface State {
    int action();
    void prepare();
}

class Method {
    ...;
    toString() { return "State1_" + param; }
}

{
    Method[] states;
    curState = -1;
    count = 0;
    int[] params = {1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000};
    for (int param: params) {
      states[count++] = new Method(param);
    }
}

@Setup(Level.Invocation)
public void prepareState() {
  if (curState != -1) {
    states[curState].prepare();
  }
}

@GenerateMicroBenchmark
public int param_1000() {
    curState = 0;
    return states[curState].action();
}

@GenerateMicroBenchmark
public int param_2000() {
    curState = 1;
    return states[curState].action();
}

@GenerateMicroBenchmark
public int param_3000() {
    curState = 2;
    return states[curState].action();
}
...
@GenerateMicroBenchmark
public int param_12000() {
    curState = 11;
    return states[curState].action();
}
4

1 に答える 1

3

ベンチマークは通常、重大な破損がなければ再利用できません。ベンチマークを単純化しようとする試みのほとんどは、信じられないほど破られました。たとえば、ここで配列を使用すると、ナノベンチマークの結果が相殺される可能性があります (たとえば、action() が小さい場合)。JavadocLevel.Invocationに記載されているように、通常は悪い考えでもあります。

結論としては、API で一部の使用が許可されているからといって、必ずしもそれを使用する必要があるとは限りません。代わりに次のことを行う必要があります。

@State(Scope.Thread)
class MyBenchmark {
    Method[] states;

    @Setup
    public void setup() {
        int[] params = {1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000};
        int count = 0;
        for (int param: params) {
            states[count++] = new Method(param);
        }
    }

    int doWork(int idx) {
        states[idx].prepare();
        return states[idx].action();
    }

    @GenerateMicroBenchmark
    public int param_1000() {
       doWork(0);
    }

    ...

    @GenerateMicroBenchmark
    public int param_12000() {
       doWork(11);
    }
}

...あるいは:

@State(Scope.Thread)
class MyBenchmark {
    Method p1000, p2000, ..., p12000;

    @Setup
    public void setup() {
        p1000 = new Method(p1000);
        p2000 = new Method(p2000);
        ...
        p12000 = new Method(p12000);
    }

    @GenerateMicroBenchmark
    public int param_1000() {
       p1000.prepare();
       return p1000.action();
    }

    ...

    @GenerateMicroBenchmark
    public int param_12000() {
       p12000.prepare();
       return p12000.action();
    }
}

別の方法として、外部からパラメーターを受け取り、Java API を使用してパラメーターを調整します。例のために:

@State(Scope.Thread)
class MyBenchmark {
    final int param = Integer.getInteger("param", 1000); 

    Method m;

    @Setup
    public void setup() {
        m = new Method(param);
    }

    @GenerateMicroBenchmark
    public int work() {
       m.prepare();
       return m.action();
    }

     public static void main(String[] args) throws RunnerException {
         Options opts = new OptionsBuilder()
                 .include(".*")
                 .jvmArgs("-Dparam=2000")
                 .build();

         RunResult runResult = new Runner(opts).runSingle();
         Result result = runResult.getPrimaryResult();

         System.out.println();
         System.out.println("API replied benchmark score: " + result.getScore() + " " + result.getScoreUnit() + " over " + result.getStatistics().getN() + " iterations");
     }
}
于 2013-11-18T18:12:58.640 に答える