JMH – Java正向循环与反向循环

关于List正向循环与反向循环的JMH基准测试 。 有一个关于反向循环更快的神话,这是真的吗?

经过测试

  • 捷运1.21
  • Java 10
  • Maven的3.6
  • CPU i7-7700

正向循环

for (int i = 0; i < aList.size(); i++) {
		String s = aList.get(i);
		System.out.println(s);
	}

反向循环

for (int i = aList.size() - 1; i >= 0; i--) {
		String s = aList.get(i);
		System.out.println(s);
	}

1.正向循环与反向循环

循环包含100万个和1000万个String对象的列表。

BenchmarkForwardReverseLoop.java
package com.mkyong.benchmark;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(value = 1, jvmArgs = {"-Xms2G", "-Xmx2G"})
@Warmup(iterations = 5)
@Measurement(iterations = 10)
@State(Scope.Benchmark)
public class BenchmarkForwardReverseLoop {

    @Param({"1000000", "10000000"})
    private int N;

    private List<String> DATA_FOR_TESTING = createData();

    public static void main(String[] argv) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(BenchmarkForwardReverseLoop.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }

    @Setup
    public void setup() {
        DATA_FOR_TESTING = createData();
    }

    @Benchmark
    public void forwardLoop(Blackhole bh) {
        for (int i = 0; i < DATA_FOR_TESTING.size(); i++) {
            String s = DATA_FOR_TESTING.get(i);
            bh.consume(s);
        }
    }

    @Benchmark
    public void reverseLoop(Blackhole bh) {
        for (int i = DATA_FOR_TESTING.size() - 1; i >= 0; i--) {
            String s = DATA_FOR_TESTING.get(i);
            bh.consume(s);
        }
    }

    private List<String> createData() {
        List<String> data = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            data.add("Number : " + i);
        }
        return data;
    }

}

2.结果

$ java -jar target\benchmarks.jar BenchmarkForwardReverseLoop

# JMH version: 1.21
# VM version: JDK 10.0.1, Java HotSpot(TM) 64-Bit Server VM, 10.0.1+10
# VM invoker: C:\Program Files\Java\jre-10.0.1\bin\java.exe
# VM options: -Xms2G -Xmx2G
# Warmup: 5 iterations, 10 s each
# Measurement: 10 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: com.mkyong.benchmark.BenchmarkForwardReverseLoop.forwardLoop
# Parameters: (N = 1000000)

# Run progress: 0.00% complete, ETA 00:10:00
# Fork: 1 of 1
# Warmup Iteration   1: 5.333 ms/op
# Warmup Iteration   2: 5.300 ms/op
# Warmup Iteration   3: 5.210 ms/op
# Warmup Iteration   4: 5.241 ms/op
# Warmup Iteration   5: 5.236 ms/op
Iteration   1: 5.127 ms/op
Iteration   2: 5.089 ms/op
Iteration   3: 5.110 ms/op
Iteration   4: 5.148 ms/op
Iteration   5: 5.233 ms/op
Iteration   6: 5.156 ms/op
Iteration   7: 5.160 ms/op
Iteration   8: 5.605 ms/op
Iteration   9: 5.169 ms/op
Iteration  10: 5.130 ms/op


Result "com.mkyong.benchmark.BenchmarkForwardReverseLoop.forwardLoop":
  5.193 ±(99.9%) 0.227 ms/op [Average]
  (min, avg, max) = (5.089, 5.193, 5.605), stdev = 0.150
  CI (99.9%): [4.966, 5.419] (assumes normal distribution)


# JMH version: 1.21
# VM version: JDK 10.0.1, Java HotSpot(TM) 64-Bit Server VM, 10.0.1+10
# VM invoker: C:\Program Files\Java\jre-10.0.1\bin\java.exe
# VM options: -Xms2G -Xmx2G
# Warmup: 5 iterations, 10 s each
# Measurement: 10 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: com.mkyong.benchmark.BenchmarkForwardReverseLoop.forwardLoop
# Parameters: (N = 10000000)

# Run progress: 25.00% complete, ETA 00:07:31
# Fork: 1 of 1
# Warmup Iteration   1: 61.361 ms/op
# Warmup Iteration   2: 61.189 ms/op
# Warmup Iteration   3: 61.570 ms/op
# Warmup Iteration   4: 61.662 ms/op
# Warmup Iteration   5: 61.604 ms/op
Iteration   1: 61.010 ms/op
Iteration   2: 61.066 ms/op
Iteration   3: 62.129 ms/op
Iteration   4: 61.854 ms/op
Iteration   5: 61.248 ms/op
Iteration   6: 61.104 ms/op
Iteration   7: 64.452 ms/op
Iteration   8: 62.398 ms/op
Iteration   9: 62.766 ms/op
Iteration  10: 66.125 ms/op


Result "com.mkyong.benchmark.BenchmarkForwardReverseLoop.forwardLoop":
  62.415 ±(99.9%) 2.535 ms/op [Average]
  (min, avg, max) = (61.010, 62.415, 66.125), stdev = 1.677
  CI (99.9%): [59.880, 64.950] (assumes normal distribution)


# JMH version: 1.21
# VM version: JDK 10.0.1, Java HotSpot(TM) 64-Bit Server VM, 10.0.1+10
# VM invoker: C:\Program Files\Java\jre-10.0.1\bin\java.exe
# VM options: -Xms2G -Xmx2G
# Warmup: 5 iterations, 10 s each
# Measurement: 10 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: com.mkyong.benchmark.BenchmarkForwardReverseLoop.reverseLoop
# Parameters: (N = 1000000)

# Run progress: 50.00% complete, ETA 00:05:02
# Fork: 1 of 1
# Warmup Iteration   1: 6.220 ms/op
# Warmup Iteration   2: 5.861 ms/op
# Warmup Iteration   3: 5.955 ms/op
# Warmup Iteration   4: 5.919 ms/op
# Warmup Iteration   5: 6.142 ms/op
Iteration   1: 5.840 ms/op
Iteration   2: 5.864 ms/op
Iteration   3: 5.892 ms/op
Iteration   4: 6.212 ms/op
Iteration   5: 5.911 ms/op
Iteration   6: 5.906 ms/op
Iteration   7: 6.055 ms/op
Iteration   8: 6.210 ms/op
Iteration   9: 6.095 ms/op
Iteration  10: 5.821 ms/op


Result "com.mkyong.benchmark.BenchmarkForwardReverseLoop.reverseLoop":
  5.980 ±(99.9%) 0.227 ms/op [Average]
  (min, avg, max) = (5.821, 5.980, 6.212), stdev = 0.150
  CI (99.9%): [5.754, 6.207] (assumes normal distribution)


# JMH version: 1.21
# VM version: JDK 10.0.1, Java HotSpot(TM) 64-Bit Server VM, 10.0.1+10
# VM invoker: C:\Program Files\Java\jre-10.0.1\bin\java.exe
# VM options: -Xms2G -Xmx2G
# Warmup: 5 iterations, 10 s each
# Measurement: 10 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: com.mkyong.benchmark.BenchmarkForwardReverseLoop.reverseLoop
# Parameters: (N = 10000000)

# Run progress: 75.00% complete, ETA 00:02:30
# Fork: 1 of 1
# Warmup Iteration   1: 55.012 ms/op
# Warmup Iteration   2: 54.479 ms/op
# Warmup Iteration   3: 54.497 ms/op
# Warmup Iteration   4: 54.677 ms/op
# Warmup Iteration   5: 54.287 ms/op
Iteration   1: 54.361 ms/op
Iteration   2: 54.432 ms/op
Iteration   3: 54.367 ms/op
Iteration   4: 54.518 ms/op
Iteration   5: 54.497 ms/op
Iteration   6: 54.369 ms/op
Iteration   7: 54.698 ms/op
Iteration   8: 54.393 ms/op
Iteration   9: 54.377 ms/op
Iteration  10: 54.675 ms/op


Result "com.mkyong.benchmark.BenchmarkForwardReverseLoop.reverseLoop":
  54.469 ±(99.9%) 0.193 ms/op [Average]
  (min, avg, max) = (54.361, 54.469, 54.698), stdev = 0.127
  CI (99.9%): [54.276, 54.661] (assumes normal distribution)


# Run complete. Total time: 00:10:04

REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.

Benchmark                                     (N)  Mode  Cnt   Score   Error  Units
BenchmarkForwardReverseLoop.forwardLoop   1000000  avgt   10   5.193 ± 0.227  ms/op
BenchmarkForwardReverseLoop.forwardLoop  10000000  avgt   10  62.415 ± 2.535  ms/op
BenchmarkForwardReverseLoop.reverseLoop   1000000  avgt   10   5.980 ± 0.227  ms/op
BenchmarkForwardReverseLoop.reverseLoop  10000000  avgt   10  54.469 ± 0.193  ms/op

结果 :在100万个循环中,正常的正向循环速度更快,但对于1000万个循环,反向循环速度更快。 但是,差异并不大。

下载源代码

$ git clone https://github.com/mkyong/jmh-benchmark
$ mvn软件包
$ java -jar target \ benchmarks.jar BenchmarkForwardReverseLoop

参考文献

  1. Java –反向循环与正向循环
  2. Java JMH基准教程
  3. 为什么反向循环不会更快

翻译自: https://mkyong.com/java/jmh-java-forward-loop-vs-reverse-loop/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值