先瞧一个例子
public class JMHSample_11_Loops_OperationsPerInvocation {
int x = 1;
int y = 2;
private int reps(int reps) {
int s = 0;
for (int i = 0; i < reps; i++) {
s += (x + y);
}
return s;
}
@Benchmark
@OperationsPerInvocation(1_000)
public int measureWrong_1000() {
return reps(1_000);
}
@Benchmark
@OperationsPerInvocation(10_000)
public int measureWrong_1000_2() {
return reps(1_000);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHSample_11_Loops_OperationsPerInvocation.class.getSimpleName())
.forks(1)
.warmupIterations(1).warmupTime(TimeValue.milliseconds(10))
.measurementIterations(2).measurementTime(TimeValue.milliseconds(300))
.build();
new Runner(opt).run();
}
}
第2个基准测试,除了@OperationsPerInvocation参数是第1个的10倍,其它都一样。结果中第2个基准测试比第1个快10几倍。
结果:
Benchmark Mode Cnt Score Error Units
JMHSample_11_Loops2.measureWrong_1000 avgt 2 0.028 ns/op
JMHSample_11_Loops2.measureWrong_1000_2 avgt 2 0.002 ns/op
官方说明
OperationsPerInvocation annotations allows to communicate the benchmark does more than one operation, and let JMH to adjust the scores appropriately.
For example, a benchmark which uses the internal loop to have multiple operations, may want to measure the performance of a single operation:
@Benchmark
@OperationsPerInvocation(10)
public void test() {
for (int i = 0; i < 10; i++) {
// do something
}
}
翻译
OperationsPerInvocation批注允许传达基准测试不止一项操作,并允许JMH适当地调整分数。
例如,使用内部循环进行多个操作的基准测试可能想要衡量单个操作的性能。
补充说明
JMH结果的统计是以操作为单位,如每一个操作的响应时间,单位时间内通过的操作数(吞吐量),一个方法视为一个操作(默认情况@OperationsPerInvocation(1))。你可以手动调整一个方法代表几个操作,如果把操作数设置为10,相同的方法,在输出结果中,吞吐量会提高10倍左右,响应时间快10倍左右。