为什么在静态上下文中访问实例字段比在JAVA中访问实例上下文要快

时间:2020-06-15 06:04:20

标签: java static instance-variables

我一直认为,从实例化方法/函数访问实例化字段应该会提高性能,因为数据应“更本地可用”(我知道这可能取决于系统和JVM),而不是从静态上下文。请参阅说明我观点的代码:

public class Lecture
{
    public static void main(String[] args)
    {
        hold h1 = new hold();   
        long start1 = System.currentTimeMillis();
            h1.accessOOPs();
        long end1 = System.currentTimeMillis();
        System.out.println("OOPS: "+ (end1 - start1));

        hold h2 = new hold();   
        long start2 = System.currentTimeMillis();
            hold.accessStatic(h2);
        long end2 = System.currentTimeMillis();
        System.out.println("Static (same class): "+ (end2 - start2));

        hold h3 = new hold();   
        long start3 = System.currentTimeMillis();
            accessStatic(h3);
        long end3 = System.currentTimeMillis();
        System.out.println("Static (different class): "+ (end3 - start3));
    }
    public static void accessStatic(hold h)
    {
        for (int i=0;i<h.vars.length;i++)
            h.vars[i] = i;
        for (int i : h.vars)
            h.var1 += i;
        for (int i: h.vars)
            h.name += i;
    }
}
class hold
{
    int var1;
    int vars[] = new int[10000];
    String name;
    public void accessOOPs()
    {
        for (int i=0;i<vars.length;i++)
            vars[i] = i;
        for (int i : vars)
            var1 += i;
        for (int i: vars)
            name += i;
    }
    public static void accessStatic(hold h)
    {
        for (int i=0;i<h.vars.length;i++)
            h.vars[i] = i;
        for (int i : h.vars)
            h.var1 += i;
        for (int i: h.vars)
            h.name += i;
    }
}

在代码中,我有3个定时示例,在其中访问/修改简单对象中的属性。第一个示例在对象中调用实例方法,因此理论上所有属性的访问速度都应更快,因为它们与该方法处于同一上下文中。第二个调用对象类中的静态函数,并每次使用点运算符访问属性。我的假设是,这会比较慢。第三个示例重复与第二个示例相同的操作,但是这次在单独的类中进行。我对收到的时间很困惑:

示例1:

  • OOPS:135
  • 静态(同班):130
  • 静态(不同班级):120

示例2:

  • 哎呀:137
  • 程序(同班):135
  • 程序(不同的班级):128

始终,当方法在单独的类中时,OOPs方法会击败静态方法,但我不明白为什么当静态方法在同一类中时,它会击败实例方法。这只是一个很小的幅度,但是非常一致。这仅是因为静态实现正在将对所访问对象的引用进行缓存吗?如果发生这种情况,那么我认为静态方法是否在单独的类中都没有关系,所以我完全感到困惑。谁能回答为什么静态方法没有明显慢的原因?

1 个答案:

答案 0 :(得分:0)

您的h3变量没有传递给任何调用,因此在第3次调用中对h2进行的计算与先前对h1 / h2的计算不同。

进行时序测试时,您仅应测量预热的代码(因为JIT编译器会稍微改变性能)。如果您修复使用h3并在循环内运行main的代码,您会发现运行之间的差异很小,我最后一次运行是

OOPS: 56
Static (same class): 56
Static (different class): 50

您可以看到,使用以下命令,accessOOP和accessStatic的字节码结构非常相似:

javap -v hold.class > hold.log
javap -v Lecture.class > lecture.log

在JDK14中,它们长114个,并且仅在字段/索引位置不同,在WINDIFF.EXE中显示出差异

Bytecode diffs accessOOPs vs accessStatic