访问本地字段与对象字段.文档错了吗?

paw*_*eba 5 java performance android jit dalvik

文档似乎是错误的.有人能告诉我哪个是真的吗?

Performance Myths部分中:

在没有JIT的设备上,缓存字段访问比重复访问字段快约20%.使用JIT,字段访问成本与本地访问大致相同.

避免内部Getters/Setters部分是:

没有JIT,直接字段访问速度比调用一个简单的getter快约3倍.使用JIT(直接字段访问与访问本地一样便宜),直接字段访问比调用一个简单的getter快约7倍.

很明显,没有JIT本地访问速度更快.同样清楚的是,访问字段比直接访问更快,而不是使用getter.

但是,为什么在第一种情况下性能提高20%,而在第二种情况下,由于同样的原因,性能提高了133%,那就是调用对象字段的JIT优化?

bfi*_*man 5

我想你在比较苹果和橘子.Performance Myths参考讨论了JI​​T对字段访问的优势,而第二个参考讨论了JI​​T对方法访问的优势.

据我了解,直接字段访问与本地访问(不是您在帖子中写的本地字段访问 - 没有本地字段之类的东西)的类比如下:

class foo {
    int bar = 42;

    int doStuff(){
        int x = 1;
        x += bar;
        x += bar;
        x += bar;
        return x;
    }
}
Run Code Online (Sandbox Code Playgroud)

每个引用bar都有相关的性能成本.一个好的编译器会认识到优化的机会并"重写"代码:

int doStuff(){
    int x = 1f;
    int local_bar = bar;
    x += local_bar;
    x += local_bar;
    x += local_bar;
    return x;
}
Run Code Online (Sandbox Code Playgroud)

如果没有JIT,这是一个方便的优化,可以让您的性能提升20%.

使用JIT,优化是不必要的,因为JIT bar首先从访问中删除了性能损失.

第二个参考描述了以下场景:

class foo {
    int bar = 42;

    int getBar() { return bar; }

    int doStuff(){
        int x = 1;
        x += getBar();
        x += getBar();
        x += getBar();
        return x;
    }
}
Run Code Online (Sandbox Code Playgroud)

每个函数调用都有相关的性能损失.编译器不能缓存多个getBar()方法调用(因为它缓存了bar前一个示例中的多个直接字段访问),因为getBar()每次调用时都可能返回一个完全不同的数字(即,如果它具有随机或时间 -基于组件的返回值).因此,它必须执行三个方法调用.

至关重要的是要理解上述功能在有或没有JIT的情况下以大约相同的速度执行.

如果您getBar()只需简单地手动替换上述功能,就bar可以提高性能.在没有JIT的机器上,性能提升大约是3倍,因为现场访问仍然有点慢,所以用稍慢的字段访问替换非常慢的方法只会产生适度的提升.但是,使用JIT,字段访问速度很快,因此使用快速字段访问替换非常慢的方法会产生更大的(7x)增强.

我希望这是有道理的!