Java - 重复的函数调用减少了执行时间 [英] Java - Repeated function call reduces execution time

查看:15
本文介绍了Java - 重复的函数调用减少了执行时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码

公共类 BenchMark {公共静态无效主要(字符串参数[]){做线性();做线性();做线性();做线性();}私人静态无效doParallel(){IntStream 范围 = IntStream.range(1, 6).parallel();long startTime = System.nanoTime();int减少=范围.reduce((a, item) -> a * item).getAsInt();long endTime = System.nanoTime();System.out.println("并行:" +reduce + " -- 时间:" + (endTime - startTime));}私人静态无效doLinear(){IntStream 范围 = IntStream.range(1, 6);long startTime = System.nanoTime();int减少=范围.reduce((a, item) -> a * item).getAsInt();long endTime = System.nanoTime();System.out.println("线性:" +reduce + " -- 时间:" + (endTime - startTime));}}

我试图对流进行基准测试,但在一次又一次调用相同的函数时,执行时间稳步减少

输出:

线性:120 -- 时间:57008226线性:120 -- 时间:23202线性:120 -- 时间:17192线性:120 -- 时间:17802进程以退出代码 0 结束

第一次和第二次执行时间存在巨大差异.

我确信 JVM 可能会在幕后做一些技巧,但谁能帮助我了解那里真正发生了什么?

有没有办法避免这种优化,以便我可以对真实的执行时间进行基准测试?

解决方案

我确信 JVM 可能会在幕后做一些技巧,但谁能帮助我了解那里真正发生了什么?

  1. 第一次调用的巨大延迟是由于整个 lambda 运行时子系统的初始化.您只需为整个申请支付一次费用.

  2. 当您的代码第一次到达任何给定的 lambda 表达式时,您需要为该 lambda 的 链接 付费(invokedynamic 调用站点的初始化).

  3. 经过一些迭代后,您将看到由于 JIT 编译器优化了您的缩减代码而获得的额外加速.

<块引用>

有没有办法避免这种优化,以便我可以对真正的执行时间进行基准测试?

您在这里要求一个矛盾:真正的"执行时间是您在 预热后得到的时间,此时所有优化都已应用.这是实际应用程序会经历的运行时.前几次运行的延迟与更广泛的情况无关,除非您对单次性能感兴趣.

为了探索,您可以查看禁用 JIT 编译时代码的行为:将 -Xint 传递给 java 命令.还有更多标志会禁用优化的各个方面.

I have this following code

public class BenchMark {
    public static void main(String args[]) {
        doLinear();

        doLinear();

        doLinear();

        doLinear();

    }


    private static void doParallel() {
        IntStream range = IntStream.range(1, 6).parallel();

        long startTime = System.nanoTime();
        int reduce = range
                .reduce((a, item) -> a * item).getAsInt();
        long endTime = System.nanoTime();
        System.out.println("parallel: " +reduce + " -- Time: " + (endTime - startTime));
    }

    private static void doLinear() {
        IntStream range = IntStream.range(1, 6);

        long startTime = System.nanoTime();
        int reduce = range
                .reduce((a, item) -> a * item).getAsInt();
        long endTime = System.nanoTime();
        System.out.println("linear: " +reduce + " -- Time: " + (endTime - startTime));
    }

}

I was trying to benchmark streams but came through this execution time steadily decreasing upon calling the same function again and again

Output:

linear: 120 -- Time: 57008226
linear: 120 -- Time: 23202
linear: 120 -- Time: 17192
linear: 120 -- Time: 17802

Process finished with exit code 0

There is a huge difference between first and second execution time.

I'm sure JVM might be doing some tricks behind the scenes but can anybody help me understand whats really going on there ?

Is there anyway to avoid this optimization so I can benchmark true execution time ?

解决方案

I'm sure JVM might be doing some tricks behind the scenes but can anybody help me understand whats really going on there?

  1. The massive latency of the first invocation is due to the initialization of the complete lambda runtime subsystem. You pay this only once for the whole application.

  2. The first time your code reaches any given lambda expression, you pay for the linkage of that lambda (initialization of the invokedynamic call site).

  3. After some iterations you'll see additional speedup due to the JIT compiler optimizing your reduction code.

Is there anyway to avoid this optimization so I can benchmark true execution time?

You are asking for a contradiction here: the "true" execution time is the one you get after warmup, when all optimizations have been applied. This is the runtime an actual application would experience. The latency of the first few runs is not relevant to the wider picture, unless you are interested in single-shot performance.

For the sake of exploration you can see how your code behaves with JIT compilation disabled: pass -Xint to the java command. There are many more flags which disable various aspects of optimization.

这篇关于Java - 重复的函数调用减少了执行时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆