简体   繁体   English

具有无限系列的Java Stream-API性能

[英]Java Stream-API performance with infinite series

I am observing some peculiar behavior with Java8 and the new Stream-API . 我正在观察Java8和新的Stream-API一些特殊行为。

I would expect the performance of the following two statements to be identical, but it's not. 我希望以下两个陈述的表现相同,但事实并非如此。

LongStream.iterate(1, n -> n + 1).limit(5000)
          .anyMatch(n -> isPerfectCube((n*n*n)+((n*n)*p)));

versus

LongStream.iterate(1, n -> n + 1)
          .anyMatch(n -> isPerfectCube((n*n*n)+((n*n)*p)));

Both statements should return true , and I wouldn't expect any performance difference given that they can both short circuit on the first match found. 两个语句都应该返回true ,并且我不会期望任何性能差异,因为它们都可以在找到的第一个匹配项上发生短路。 The only difference in the statements is that one is bounded in an upper limit on the range of numbers to iterate, while the other is not. 这些陈述的唯一区别是,一个是在要迭代的数字范围的上限,而另一个不是。

Can someone explain to me why one would run faster and use less memory than the other? 有人可以向我解释为什么一个人跑得更快并且使用的内存比另一个少?

There are some values of p where the condition is true for large values of n . 有一些p值,其中条件对于大的n值是真的。 For example with p = 3 , the condition becomes true for n = 50_331_648 . 例如,对于p = 3 ,对于n = 50_331_648 ,条件变为真。 In that case, the limit of 5000 will of course win in terms of performance but the two calculations won't return the same result. 在这种情况下,5000的限制当然会在性能方面获胜,但两次计算不会返回相同的结果。

I have randomly picked a p (3002) that returns true for n less than 5000 and the results are very close (although the version with limit is slightly slower, probably because of the extra condition n < 5000 ). 我已经随机挑选一个p (3002),则返回true为n小于5000和结果非常接近(虽然版本limit是可能是因为额外的条件稍微慢一些, n < 5000 )。

Benchmark results (in micro-seconds per call to anyMatch ): 基准测试结果(每次调用anyMatchanyMatchanyMatch ):

Benchmark                    Mode   Samples         Mean   Mean error    Units
c.a.p.SO24003674.limit       avgt         5      130.165        2.663    us/op
c.a.p.SO24003674.noLimit     avgt         5      126.876        2.440    us/op

Benchmark code (using jmh): 基准代码(使用jmh):

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
@Fork(1)
public class SO24003674 {

  private int p = 3002;

  @GenerateMicroBenchmark
  public boolean limit() {
    return LongStream.iterate(1, n -> n + 1).limit(5000)
              .anyMatch(n -> isPerfectCube((n * n * n) + ((n * n) * p)));
  }

  @GenerateMicroBenchmark
  public boolean noLimit() {
    return LongStream.iterate(1, n -> n + 1)
              .anyMatch(n -> isPerfectCube((n * n * n) + ((n * n) * p)));
  }

  private static boolean isPerfectCube(long n) {
    long tst = (long) (Math.cbrt(n) + 0.5);
    return tst * tst * tst == n;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM