1. 测试循环代码耗时

加入我们希望测试一段代码, 循环 10w次, 耗时, 我们可以这么写

  1. @Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
  2. @Measurement(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
  3. @State(Scope.Thread)
  4. @BenchmarkMode(Mode.AverageTime)
  5. @OutputTimeUnit(TimeUnit.NANOSECONDS)
  6. public class Sample_11_Loops {
  7. int x = 1;
  8. int y = 2;
  9. private int reps(int reps) {
  10. int s = 0;
  11. for (int i = 0; i < reps; i++) {
  12. s += (x + y);
  13. }
  14. return s;
  15. }
  16. @Benchmark
  17. public int measure100000() {
  18. return reps(100_000);
  19. }
  20. public static void main(String[] args) throws RunnerException {
  21. Options opt = new OptionsBuilder()
  22. .include(Sample_11_Loops.class.getSimpleName())
  23. .forks(1)
  24. .jvmArgs("-server")
  25. .build();
  26. new Runner(opt).run();
  27. }
  28. }

测试结果:

  1. Benchmark Mode Cnt Score Error Units
  2. Sample_11_Loops.measure100000 avgt 1679.310 ns/op

2. @OperationsPerInvocation

但是我们需求有一点小改变
我们希望JMH帮我们计算出, 平均每次循环的耗时
那么我们就需要告诉JMH, 方法被调用一次, 会有多少次循环

  1. @Benchmark
  2. @OperationsPerInvocation(100_000)//告诉JMH这里重复了100000遍, 统计的时候调用一次要当做调用100000次来计算性能
  3. public int measure100000() {
  4. return reps(100_000);
  5. }
  • 这里我们使用 @OperationsPerInvocation(100_000)注解, 告诉JMH一次顶10w次

统计结果

  1. Benchmark Mode Cnt Score Error Units
  2. Sample_11_Loops.measure100000 avgt 0.018 ns/op

这样JMH就会直接给我们把结果计算出来, 在原来的数值上除以10w


3. 谨慎使用循环

要注意, 循环写在测试代码中, JIT又会开始起作用, 可能会对测试结果会有极大的影响
例如这个例子:

  1. @Benchmark
  2. public int measure1() {
  3. return reps(1);
  4. }
  5. @Benchmark
  6. @OperationsPerInvocation(100_000)//告诉JMH这里重复了100000遍, 统计的时候调用一次要当做调用100000次来计算性能
  7. public int measure100000() {
  8. return reps(100_000);
  9. }

根据我们的直觉, 这两个例子应该得出的结果是一致的
测试结果:

  1. Benchmark Mode Cnt Score Error Units
  2. Sample_11_Loops.measure1 avgt 1.471 ns/op
  3. Sample_11_Loops.measure100000 avgt 0.017 ns/op

但实际上结果不一致,
按代码来看, 两个Benchmark算出的都是1次循环执行1次的平均耗时
但连续执行10w次的方法 性能远远好于执行1次的方法
这就是因为JIT对循环进行了优化, 导致了循环越多性能越强


所以我们在使用循环的时候, 要尽量与实际业务保持一致, 这样可以得到最真实的结果