访问本地字段vs对象字段。 doc是错误的吗?

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

在性能神话部分是:

在没有JIT的设备上,缓存字段访问速度比重复访问字段快20%左右 。 通过JIT,现场访问成本与本地访问大致相同。

避免内部获取者/设置者部分是:

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

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

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


我想你是在比较苹果和橘子。 “性能神话”参考讨论了JI​​T用于字段访问的优点,而第二篇参考文献讨论了JI​​T用于方法访问的优点。

据我所知,直接字段访问与本地访问(不是您在本文中撰写的本地字段访问 - 本地字段没有此类事物)类似如下:

class foo {
    int bar = 42;

    int doStuff(){
        int x = 1;
        x += bar;
        x += bar;
        x += bar;
        return x;
    }
}

每个参考bar有一个相关的性能开销。 一个好的编译器会认识到优化和'重写'代码的机会,如下所示:

int doStuff(){
    int x = 1f;
    int local_bar = bar;
    x += local_bar;
    x += local_bar;
    x += local_bar;
    return x;
}

如果没有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;
    }
}

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

理解上述功能在有或没有JIT的情况下以大致相同的速度执行是非常重要的

如果你要手动更换getBar()与简单地在上面的功能bar ,你会获得性能提升。 在没有JIT的机器上,性能提升大约是3倍,因为现场访问仍然有点慢,所以用稍慢的现场访问替换非常慢的方法只会产生适度的提升。 然而,使用JIT时,现场访问速度很快,因此用快速现场访问取代非常慢的方法会产生更大的(7倍)提升。

我希望这是有道理的!


我想你可能会比较苹果与橙子。 在第一个报价中:

 caching field accesses is about 20% faster than repeatedly accesssing the field

意味着只有在直接字段访问期间,缓存策略才能提高性能,而无需JIT编译。 换一种说法:

int a = this.field;
if (a == 1)
...
if (a == 7) // etc.

产生更好的性能

if (this.field == 1)
....
if (this.field == 7) //etc.

该报价表明,通过反复引用该字段而不是将其存储在本地,您将受到惩罚。

第二个引言表明,如果没有JIT使用简单的getter / setter比直接字段访问要慢,例如:

if (this.getField()) // etc.

比:慢

if (this.field) // etc.

我不认为文件是错误的,或者一个声明破坏了另一个声明。


这只是一个受过教育的猜测,我不知道Dalvik内部。 但请注意,在第一种情况下,将本地访问的性能与字段访问进行比较,而在第二种情况下,将字段访问与简单的方法调用进行比较。 还要注意,通过添加JIT,相同代码的x%加速时间不会少x%,我们正在谈论相对性能:(a)解释的本地访问速度比解释字段访问速度快20%,( b)JIT本地访问速度与JIT'd字段访问速度一样快(c)解释的本地访问速度与JIT本地/字段访问速度一样快。 事实上,这很可能会变慢。

在大多数虚拟机架构中,读取本地语言是一种内存访问,而不是寄存器访问(我们正在讨论机器寄存器,而不是Dalvik寄存器)。 读取字段更慢 - 我无法确定为什么(我的猜测是第二次查找,读取寄存器和对象字段),但无论如何它更复杂。 另一方面,JIT可以将字段和本地信息放入寄存器中(这就是我必须假设的解释性能平等的方法,实际上有JIT这样做 - 我只是不知道它是否适用于此)和消除了大部分开销。

对于方法调用,假设Dalvik JIT没有内联方法(这是隐含的),那么在实际调用之前有一些额外开销,即使在JIT调用时调用代价也很昂贵:必须将寄存器保存到堆栈,必须在之后恢复它们,不能尽可能优化,因为不是所有的代码都可见。 一个通话相对而言比较无代码的代码更昂贵,因为这个无需通话的替代方式非常快速,并不是因为解释器在进行通话时效果更好(它不会,它在执行其他任何操作时都会变得很慢)。 例如,通话不会阻止优化,因为没有优化。

链接地址: http://www.djcxy.com/p/23677.html

上一篇: Accessing local field vs object field. Is doc wrong?

下一篇: Android Dev: Avoiding Internal Getters/Setters?