2013-10-05 10 views
6

Ich verwende jmh(), um eine Methode zu benchmarken. Ich habe auch die Menge von Parametern, die ich als Argumente verwenden möchte, um diese Methode auszuführen. Ist es möglich, eine Methode für jeden einzelnen Parameterwert zu generieren (mit Annotation @GenerateMicroBenchmark)?Wie generiere ich Methoden in jmh-Benchmarks?

Jetzt benutze ich die ähnliche Umsetzung, aber es ist nicht so praktisch, weil ich viel einheitlichen Code von Hand schreiben:

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(); 
} 

Antwort

3

Das Benchmarks in der Regel nicht selbst zur Wiederverwendung verleihen ohne etwas ernsthaften Bruch. Die meisten Versuche, Leute zu sehen, die versuchten, ihre Benchmarks zu vereinfachen, brachen sie durch ihren Glauben. Wenn Sie hier beispielsweise Arrays verwenden, werden die Ergebnisse für Nano-Benchmarks möglicherweise ausgeglichen (z. B. wenn action() klein ist). Level.Invocation ist normalerweise eine schlechte Idee, wie in its Javadoc angegeben.

Die Quintessenz ist, nur weil einige Verwendung von API erlaubt ist, bedeutet es nicht unbedingt, dass Sie es verwenden sollten. Hier ist, was Sie sollten stattdessen tun:

@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); 
    } 
} 

... oder auch:

@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(); 
    } 
} 

Die Alternative die Parameter von außen würde akzeptieren, und mit Hilfe von Java API die Parameter jonglieren. Zum Beispiel:

@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"); 
    } 
} 
Verwandte Themen