访问本地字段vs对象字段。 doc是错误的吗?
文件似乎是错误的。 有人能告诉我哪个是真的吗?
在性能神话部分是:
在没有JIT的设备上,缓存字段访问速度比重复访问字段快20%左右 。 通过JIT,现场访问成本与本地访问大致相同。
避免内部获取者/设置者部分是:
没有JIT,直接字段访问比调用一个简单的getter快3倍 。 使用JIT(直接字段访问与访问本地一样便宜),直接字段访问比调用一个简单的getter快7倍 。
很明显,没有JIT本地访问速度更快。 同样清楚的是访问字段比直接访问比getter更快。
但是,为什么在第一种情况下,性能会提高20%,而在第二种情况下,出于同样的原因,性能会提高133% ,这就是调用对象字段的JIT优化?
我想你是在比较苹果和橘子。 “性能神话”参考讨论了JIT用于字段访问的优点,而第二篇参考文献讨论了JIT用于方法访问的优点。
据我所知,直接字段访问与本地访问(不是您在本文中撰写的本地字段访问 - 本地字段没有此类事物)类似如下:
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