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

问题描述 投票:0回答:1

我一直认为,与从静态上下文中访问成员相比,从实例方法函数中访问实例字段应该会带来一些性能上的提升,因为数据应该 "更本地可用"(我知道这可能取决于系统和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

  • OOPS: 135
  • 静态(同一类):130
  • 静态(不同类):120

示例运行2。

  • OOPS:137
  • 程序性(同级):135人
  • 程序性(不同等级):128人

当OOPs方法在单独的类中时,OOPs方法一贯地击败了Static方法,但我不明白为什么当静态方法在同一个类中时,它会击败实例方法。虽然只是微弱的差距,但却非常一致。这种情况是否只是因为静态实现缓存了对被访问对象的引用而发生的?如果出现这种情况,那么我认为静态方法是否在一个单独的类中并不重要,所以我完全搞不懂。谁能回答为什么静态方法没有明显的慢?

java static instance-variables
1个回答
0
投票

你的h3变量并没有传递给任何调用,所以在第3次调用中对h2所做的计算与前面h1h2的计算是不同的。

在做时序测试时,你应该只测量预热后的代码(因为JIT编译器会改变一些性能)。如果你固定使用h3,并在循环里面运行main的代码,你会发现运行之间的差别很小,我最后得到的运行结果是

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

可以看到,使用accessOOPs和accessStatic的字节码结构非常相似。

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

在JDK14中,它们都是114项的长度,不同的只是fieldindex的位置,在WINDIFF.EXE中显示了它们的不同之处。

Bytecode diffs accessOOPs vs accessStatic

© www.soinside.com 2019 - 2024. All rights reserved.