繁体   English   中英

为什么调用一个函数比不调用一个函数要快?

[英]Why is calling a function faster than not calling a function?

我尝试了以下代码:

public class Test {
    public static void main(String[] args) {
        int x = 9, y = 9, z = 0;
        long startTime = System.currentTimeMillis();
        // System.out.println("loop one start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = x + y;
            }
        }
        System.out.println("loop one use time = " + (System.currentTimeMillis() - startTime) + ",z = " + z);

        startTime = System.currentTimeMillis();
        // System.out.println("loop two start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = sum(x, y);
            }
        }
        System.out.println("loop two use time = " + (System.currentTimeMillis() - startTime) + ",z = " + z);

    }

    public static int sum(int x, int y) {
        int t;
        t = x + y;
        return t;
    }
}

控制台的输出为:

loop one use time = 216,z = 18
loop two use time = 70,z = 18.

看来第二个循环比第一个循环花费的时间更少! 我不明白为什么会这样。 感谢您的帮助。


更新:我交换了两个循环,现在循环一会花费更少的时间!

loop two use time = 219,z = 18
loop one use time = 69,z = 18

编写正确的微基准测试非常耗时且容易出错。 我建议仅使用像Caliper这样已经可用的库来进行微基准测试。

您的微基准测试有很多缺陷,将导致无法预测的结果:

  1. 您没有做任何热身。
  2. 您正在对main方法中的这两种方法进行基准测试,从而使JIT编译器更难以优化代码。
  3. 代码“ z = x + y;” 实际上降到了“ z = 9 + 9;” 并且在循环过程中不会改变,因此可以将循环完全优化为简单表达式“ z = 18”。

无论如何,这是使用Caliper进行相应基准测试的代码:

@VmOptions("-server")
public class Test {

    @Benchmark
    public int timeSum1(long reps) {
        int dummy = 0; 
        int x = 9, y = 9;
        for (int j = 0; j < reps; j++) {
            dummy = x + y;
        }
        return dummy;
    }

    @Benchmark
    public int timeSum2(long reps) {
        int dummy = 0; 
        int x = 9, y = 9;
        for (int j = 0; j < reps; j++) {
            dummy = sum(x, y);
        }
        return dummy;
    }

    public static int sum(int x, int y) {
        int t;
        t = x + y;
        return t;
    }
}

您可以在此处查看该基准测试的结果:

结果与预期的一样:两种方法大约需要相同的时间,因为JIT编译器可以内联它们。 使用-server运行这两种方法仍需花费大约相同的时间,但在优化方面要好一些。

从阅读评论中我有这个想法,请尝试以下代码

public class Test {
    public static void main(String[] args) {
        int x = 9, y = 9, z = 0;
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = x + y;
                // z = sum(x, y);
            }
        }
        long startTime = System.currentTimeMillis();
        // System.out.println("loop one start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = x + y;
            }
        }
        System.out.println("loop one use time = "
                + (System.currentTimeMillis() - startTime) + ",z = " + z);

        startTime = System.currentTimeMillis();
        // System.out.println("loop two start time = " + startTime);
        for (int i = 0; i < 10000; i++) {
            for (int j = 0; j < 10000; j++) {
                z = sum(x, y);
            }
        }
        System.out.println("loop two use time = "
                + (System.currentTimeMillis() - startTime) + ",z = " + z);

    }

    public static int sum(int x, int y) {
        int t;
        t = x + y;
        return t;
    }
}

结果将表明两个循环具有相同的时间,这是因为JVM已经预热了其内部功能并准备好使用自己的脚趾。 :)

这也意味着您不能直接关联某些代码所使用的时间与其算法直接相关,因此您需要控制相同的环境和参数来控制代码的时间消耗。

暂无
暂无

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

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