Java性能:For-eaching与Streaming

在for循环中向上或向下计数是最有效的迭代方式吗? 有时答案既不是。 阅读这篇文章,了解不同迭代品种的影响。

迭代性能

关于如何以高性能进行迭代有很多观点。 Java中的传统迭代方式是一个for循环,该循环从零开始,然后计数到一些预定义的数字:

private static final int ITERATIONS = 10_000;

@Benchmark
public int forUp() {
    int sum = 0;
    for (int i = 0; i < ITERATIONS; i++) {
        sum += i;
    }
    return sum;
}

有时,我们遇到一个for循环,该循环以预定的非负值开始,然后递减计数。 这在JDK本身中非常普遍,例如在String类中。 这是通过递减而不是递增来解决先前问题的示例。

@Benchmark
public int forDown() {
    int sum = 0;
    for (int i = ITERATIONS; i-- > 0;) {
        sum += i;
    }
    return sum;
}

我认为,这样做的理由是,检查值与零的关系可能比测试值与任何其他任意值的关系更有效。 实际上,我所知道的所有CPU都有机器码指令,可以检查给定值与零的关系。 另一个想法是,上面给出的递减计数习惯似乎只检查一次循环变量(它同时检查值,然后减小它),而不是顶部的常规示例。 我怀疑这对当今高效的JIT编译器影响很小或没有影响,后者将能够像优化第二个迭代一样优化第一个迭代。 当代码在解释模式下运行时可能会产生影响,但是本文中未对此进行检查。

另一种方法是使用
IntStream看起来像这样:

@Benchmark
public int stream() {
    return IntStream.range(0, ITERATIONS)
        .sum();
}

如果大型迭代需要更高的性能,则只需在流中添加.parallel()运算符就可以使流并行变得相对容易。 本文未对此进行检查。

Graal VM下的性能

在我的笔记本电脑(MacBook Pro,2015年中,2.2 GHz Intel Core i7)上的GraalVM(rc-11,以及GraallVM附带的新C2编译器)下运行这些测试可以得出以下结果:

Benchmark              Mode  Cnt       Score       Error  Units
ForBenchmark.forDown  thrpt    5  311419.166 ±  4201.724  ops/s
ForBenchmark.forUp    thrpt    5  309598.916 ± 12998.579  ops/s
ForBenchmark.stream   thrpt    5  312360.089 ±  8291.792  ops/s

对于流解决方案是最快的解决方案(尽管误差在误差范围内),这可能会让某些人感到意外。

上一篇文章中 ,我介绍了与传统命令式代码相比,流和声明式编程在代码度量方面的一些优势。 我尚未测试过冷代码段的性能(即,在JIT启动之前)。

聪明的数学

根据数学,我们记得从零开始的连续数字的总和为N *(N + 1)/ 2,其中N是序列中的最高数字。 运行此基准测试:

@Benchmark
public int math() {
    return ITERATIONS * (ITERATIONS + 1) / 2;
}

使我们的性能比以前的实现提高了1000倍以上:

Benchmark           Mode  Cnt          Score          Error  Units
ForBenchmark.math  thrpt    5  395561077.984 ± 11138012.141  ops/s

迭代次数越多,收益越大。 聪明有时会胜过蛮力。

超快速数据流

使用Speedment HyperStream,可以从数据库中获得类似的性能。 在HyperStream上阅读更多信息

结论

在某些常用的硬件/ JVM上,无论我们在for循环中向上还是向下进行迭代都没有关系。 较新的JVM能够优化流迭代,因此与for循环相比,它们具有同等甚至更好的性能。

在我看来,与for循环相比,流代码通常更具可读性,因此,我相信流在某些将来可能是事实上的迭代发明。

使用Speedment HyperStream可以高性能地流传输数据库内容。

翻译自: https://www.javacodegeeks.com/2019/09/java-performance-for-eaching-vs-streaming.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值