java - 等效静态和非静态方法的速度差异很大

标签 java performance object methods static

在这段代码中,当我在 main 方法中创建一个对象,然后调用该对象方法: ff.twentyDivCount(i)(runs in 16010 ms) 时,它运行速度比使用以下注释调用它快得多:twentyDivCount(i)(运行时间为 59516 毫秒)。当然,当我在不创建对象的情况下运行它时,我将方法设为静态,因此可以在 main 中调用它。

public class ProblemFive {

    // Counts the number of numbers that the entry is evenly divisible by, as max is 20
    int twentyDivCount(int a) {    // Change to static int.... when using it directly
        int count = 0;
        for (int i = 1; i<21; i++) {

            if (a % i == 0) {
                count++;
            }
        }
        return count;
    }

    public static void main(String[] args) {
        long startT = System.currentTimeMillis();;
        int start = 500000000;
        int result = start;

        ProblemFive ff = new ProblemFive();

        for (int i = start; i > 0; i--) {

            int temp = ff.twentyDivCount(i); // Faster way
                       // twentyDivCount(i) - slower

            if (temp == 20) {
                result = i;
                System.out.println(result);
            }
        }

        System.out.println(result);

        long end = System.currentTimeMillis();;
        System.out.println((end - startT) + " ms");
    }
}

编辑:到目前为止,似乎不同的机器会产生不同的结果,但使用 JRE 1.8.* 似乎可以始终如一地重现原始结果。

最佳答案

使用 JRE 1.8.0_45 我得到了类似的结果。

调查:

  1. 使用 -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining VM 选项运行 java 表明这两种方法都已编译和内联
  2. 查看为方法本身生成的程序集没有显着差异
  3. 然而,一旦它们被内联,在 main 中生成的程序集就大不相同了,实例方法被更积极地优化,尤其是在循环展开方面

然后我再次运行您的测试,但使用不同的循环展开设置来确认上述怀疑。我运行了你的代码:

  • -XX:LoopUnrollLimit=0 并且这两个方法运行缓慢(类似于带有默认选项的静态方法)。
  • -XX:LoopUnrollLimit=100 并且两个方法都运行得很快(类似于带有默认选项的实例方法)。

作为一个结论,似乎在默认设置下,热点 1.8.0_45 的 JIT 在方法为静态时无法展开循环(虽然我不确定为什么会这样行为方式)。其他 JVM 可能会产生不同的结果。

关于java - 等效静态和非静态方法的速度差异很大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30454904/

相关文章:

php - 使用我的mysql或文本文件存储数据以便快速访问

perl - 如果没有分配给任何变量,对象是否可访问?

Java 骰子游戏生成新数字时遇到问题

java - 在子类java中更改类变量类型

java - 如何在 Wicket 口创建元素 <a>

java - 如何从 java 中的子项为最终静态变量赋值?

java - 带空行的缓冲阅读器 readLine()

algorithm - 有效地找到数组中元素的等级?

java - 将大样本放在二叉搜索树上(不平衡)

php - 在 PHP 中跨类共享类实例