- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我不明白为什么要使用 Stream api 对同一个数组进行多次迭代结果是这样的表现!
请看下面的代码。
public class WhyIsDifferent {
public static void main(String[] args) {
int[] values = getArray();
Iterate(values, 598, 600); // 70 ms
Iterate(values, 200, 202); // 0 ms
Iterate(values, 700, 702); // 0 ms
Iterate(values, 300, 310); // 1 ms
}
public static void Iterate(int[] values, int from, int to) {
long start = System.currentTimeMillis();
IntStream.of(values).filter(i -> i < to && i > from)
.forEach(i ->
System.out.println(i) // do a something
);
System.out.println("Time:" + (System.currentTimeMillis() - start));
}
public static int[] getArray() {
int[] values = new int[1000];
for (int i = 0; i < 1000; i++) {
values[i] = i;
}
return values;
}
}
确定 JVM 优化了代码,但我不知道这是怎么发生的?太棒了!你知道为什么会这样吗?
--
我在 Ubuntu 14.04//Oracle jdk/intel cpu 上测试。
最佳答案
它不是 JIT 编译器。这 70 毫秒中的大部分时间都花在了整个 lambda 子系统的初始化上(该逻辑的入口点可能是 LambdaMetaFactory
类),还有相当一部分时间花在了 lambda Bootstrap 调用上(< em>linkage 阶段,如用户 fge 所述)。看看这个方法,和你的一样,但是所有的步骤都是单独测量的(我使用的是 nanoTime
):
public static void Iterate(int[] values, int from, int to) {
long start = System.nanoTime();
final IntPredicate predicate = i -> i < to && i > from;
System.out.println("Predicate lambda creation time:" + NANOSECONDS.toMillis(System.nanoTime() - start));
start = System.nanoTime();
final IntConsumer action = System.out::println;
System.out.println("Action lambda creation time:" + NANOSECONDS.toMillis(System.nanoTime() - start));
start = System.nanoTime();
final IntStream stream = IntStream.of(values).filter(predicate);
System.out.println("Stream creation time:" + NANOSECONDS.toMillis(System.nanoTime() - start));
start = System.nanoTime();
stream.forEach(action);
System.out.println("Stream consumption time:" + NANOSECONDS.toMillis(System.nanoTime() - start));
}
这是我机器上打印的内容:
Predicate lambda creation time:53
Action lambda creation time:2
Stream creation time:2
599
Stream consumption time:1
Predicate lambda creation time:0
Action lambda creation time:0
Stream creation time:0
201
... all timings zero from here on...
您可以看到,第一次调用的全部开销都在 lambda 创建部分(仅在第一次运行时,包括一般初始化和链接),流创建也需要一些时间。在所有情况下,实际流消耗时间为零。
对于当前版本的 HotSpot,这种效果绝对值得您牢记:lambda bootstrap 是一件昂贵的事情。
最后一点:如果您重新排序 lambda 创建语句,您会发现大部分时间都停留在要创建的第一个 lambda 上。这向我们表明,它实际上只是承担大部分初始化成本的 lambda 的第一个整体创建。
关于java - 对 Java8 Stream 性能感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27109944/
我正在尝试学习Rust。我正在阅读一本书online,该书实现了unix程序cat。现在,我试图读取作为像cargo run file1.txt file2.txt这样的参数传递的文件的内容,但是程序
我在 GHC 8.0.1 中遇到了一个带有种类索引 (?) GADT 的奇怪情况,其中在类型与种类签名中引入 foralls 会产生不同的类型检查行为。 考虑以下数据类型: {-# LANGUAGE
我正在使用 Perl 5.10 开发应用程序,HTML::Mason和 Apache 2.2。这是我第一次在大型项目中使用 Perl 5.10。我每隔一段时间就会出现奇怪的行为。应用程序因一个非常奇怪
我正在尝试将文件上传到aws中的rust中,因为我使用的是 rusoto_s3 的s3 rust客户端,当这些部分从单个线程发送时,我设法使分段上传代码正常工作不是我想要的,我想上传大文件,并且希望能
我是一名优秀的程序员,十分优秀!