Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么方法访问似乎比字段访问快?_Java_Optimization_Benchmarking - Fatal编程技术网

Java 为什么方法访问似乎比字段访问快?

Java 为什么方法访问似乎比字段访问快?,java,optimization,benchmarking,Java,Optimization,Benchmarking,我做了一些测试来找出使用getter/setter和直接字段访问之间的速度差异。我编写了一个简单的基准测试应用程序,如下所示: public class FieldTest { private int value = 0; public void setValue(int value) { this.value = value; } public int getValue() { return this.value;

我做了一些测试来找出使用getter/setter和直接字段访问之间的速度差异。我编写了一个简单的基准测试应用程序,如下所示:

public class FieldTest {

    private int value = 0;

    public void setValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    public static void doTest(int num) {
        FieldTest f = new FieldTest();

        // test direct field access
        long start1 = System.nanoTime();

        for (int i = 0; i < num; i++) {
            f.value = f.value + 1;
        }
        f.value = 0;

        long diff1 = System.nanoTime() - start1;

        // test method field access
        long start2 = System.nanoTime();

        for (int i = 0; i < num; i++) {
            f.setValue(f.getValue() + 1);
        }
        f.setValue(0);

        long diff2 = System.nanoTime() - start2;

        // print results
        System.out.printf("Field Access:  %d ns\n", diff1);
        System.out.printf("Method Access: %d ns\n", diff2);
        System.out.println();
    }

    public static void main(String[] args) throws InterruptedException {
        int num = 2147483647;

        // wait for the VM to warm up
        Thread.sleep(1000);

        for (int i = 0; i < 10; i++) {
            doTest(num);
        }
    }

}
公共类现场测试{
私有int值=0;
公共无效设置值(int值){
这个值=值;
}
public int getValue(){
返回此.value;
}
公共静态void doTest(int num){
现场测试f=新的现场测试();
//测试直接现场访问
long start1=System.nanoTime();
for(int i=0;i
无论何时运行,我都会得到一致的结果,例如:

我想知道是否有人能向我解释为什么字段访问似乎比getter/setter方法访问慢,以及为什么最后8次迭代执行得非常快



编辑:考虑到
assylias
Stephen C
的评论,我将代码更改为获得稍微不同结果的代码:。

原因是您的基准被破坏

第一次迭代使用解释器完成

Field Access:  1528500478 ns
Method Access: 1521365905 ns
第二次迭代首先由解释器完成,然后我们转而运行JIT编译的代码

Field Access:  1550385619 ns
Method Access: 47761359 ns
其余的迭代都是使用JIT编译代码完成的

Field Access:  68 ns
Method Access: 33 ns

etcetera
它们速度惊人的原因是JIT编译器已经优化了循环。它检测到它们对计算没有贡献任何有用的东西。(不清楚为什么第一个数字似乎始终比第二个数字快,但我怀疑优化后的代码是否以任何有意义的方式衡量了字段访问和方法访问。)



重新更新代码/结果:很明显,JIT编译器仍在优化循环。

我认为编译器无论如何都会将getter内联。您是否检查了字节码?
/*等待VM预热*/Thread.sleep(1000)-它不是这样工作的。如果JVM什么都不做,它就不会预热。。。你的微基准测试有几个缺陷。特别是:(i)您实际上不允许JVM预热(ii)您要测试的两个路径使用相同的方法,这可能会阻止某些优化。@jlordo-内联是由JIT编译器完成的。我不会在字节码中出现。我已经检查了字节码(),看起来编译器没有内联它。然而,正如Stephen C所说,它是由JIT编译器内联的。事实上,从时间上看,整个循环似乎已经被优化了……因此@Stephen使用访问器方法不仅有利于封装,而且有利于速度??听到这个消息太好了@维克多-我不相信你能得出这样的结论。事实上,我不相信你能从这个基准中得出任何结论。这简直是有缺陷的汉克斯·斯蒂芬!我懂了。。。我开始这么想。所以,如果你寻求速度,使用直接访问,如果你想要更灵活的设计,使用访问器方法?(很抱歉这个离题的问题!)我认为你也不能得出这个结论。我的理解是,一个好的JIT编译器将内联一个简单的getter或setter,以便它们执行与直接字段访问/更新相同的操作。