【问题标题】:Java 8 forEach Loop Takes much time, why?Java 8 forEach 循环需要很多时间,为什么?
【发布时间】:2016-05-25 11:01:06
【问题描述】:

我有一个 ArrayList 围绕 3483 对象准备合并到数据库中。 当我使用 lambda 表达式时 - 它需要 85122 毫秒。 但是for(Obj o : list) 只需要 25 毫秒。为什么 Java8 需要多 3404 倍的时间?

List<CIBSubjectData> list1 = .....

list1.forEach(data ->
     merge(data)
);

for (CIBSubjectData data : list1) {
    merge(data);
}

【问题讨论】:

  • 试过并行流:list1.parallelStream().forEach(data -> merge(data)) ?
  • 你可能会在this question找到答案。
  • 我认为我们需要更多的上下文和/或代码。 forEach+lambda 确实需要更长的时间,但在一般情况下,远不及 那个 更长的时间。我刚刚对有 400k 个条目的LinkedList 进行了一次简单的检查(即not reliable),forEach 花了 40 毫秒;增强 for 看 5ms。
  • 你在merge(data)里面做什么?

标签: java


【解决方案1】:

我相信您没有使用正确的微基准设置。您正在比较 bytecode instrumentation framework(用于在 runtime 生成 lambda 字节码的 ASM)+lambda execution timeexecution time of the loop 的预热。

检查performance-difference-between-java-8-lambdas-and-anonymous-inner-classes 和链接文档的答案。链接的文档对幕后处理有深入的了解。

edit提供一个小sn-p来演示以上内容。

public class Warmup {
    static int dummy;

    static void merge(String s) {
        dummy += s.length();
        dummy++;
        dummy -= s.length();
    }

    public static void main(String[] args) throws IOException {
        List<String> list1 = new ArrayList<>();
        Random rand = new Random(1);

        for (int i = 0; i < 100_000; i++) {
            list1.add(Long.toString(rand.nextLong()));
        }

        // this will boostrap the bytecode instrumentation
        // Stream.of("foo".toCharArray()).forEach(System.out::println);
        long start = System.nanoTime();
        list1.forEach(data -> merge(data));

        long end = System.nanoTime();
        System.out.printf("duration: %d%n", end - start);
        System.out.println(dummy);
    }
}

如果您在发布代码时运行代码,我机器上的打印持续时间是

duration: 71694425

如果您取消注释 Stream.of(... 行(仅第一次使用字节码检测框架)打印的持续时间是

duration: 7516086

这只是初始运行的 10% 左右。

注意只是为了明确。不要使用上述基准。看看jmh 有这样的要求。

【讨论】:

  • OP 报告“85122 毫秒”;那是一分半钟。我不会称其为“微基准测试”,也不认为这完全是由于热身......
  • @tobias_k 我同意。但是for(Obj o : list) takes only 25 ms 是。所以他肯定想做一个微基准。否则循环也会花费更长的时间。对于 lambda 需要更长的时间。我们需要来自 OP 的更多意见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
  • 1970-01-01
  • 2012-01-14
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多