问题描述
我有一个运行4096次的for循环,它应该尽可能快。性能在这里非常重要。目前我在循环中使用getter方法,它只返回在循环进行时不会改变的字段中的值或对象。
I have a for loop which runs 4096 times and it should be as fast as possible. Performance is really important here. Currently I use getter methods inside the loop which just return values or objects from fields which don't change while the loop is in progress.
示例:
for (;;) {
doSomething(example.getValue());
}
使用getter是否有任何开销?使用以下方式更快吗?
Is there any overhead using getters? Is it faster using the following way?
示例:
Object object = example.getValue();
for (;;) {
doSomething(object);
}
如果是,对于访问<$ c $等公共字段也是如此c> example.value ?
编辑:我不使用 System.out.println()循环内code>。
编辑:某些字段不是 final
。没有字段 volatile
且没有方法(getter) synchronized
。
Some fields are not final
. No fields are volatile
and no method (getter) is synchronized
.
推荐答案
当时,在循环外获取对象引用( Object object = example.getValue();
)可能比在循环中调用getter更快(或者至少永远不会慢)因为
As Rogério answered, getting the object reference outside the loop (Object object = example.getValue();
) will likely be faster (or will at least never be slower) than calling the getter inside the loop because
- 在最糟糕的情况下,
example.getValue()
实际上可能会做一些计算量很大的东西尽管应该是微不足道的,但在后台仍然存在。通过分配一次引用并重新使用它,您只需执行一次这种昂贵的计算。 - 在最佳情况下,
example.getValue()
做了一些微不足道的事情,比如返回值;
所以在JIT编译器。
- in the "worst" case,
example.getValue()
might actually do some very computationally-expensive stuff in the background despite that getter methods are supposed to be "trivial". By assigning a reference once and re-using it, you do this expensive computation only once. - in the "best" case,
example.getValue()
does something trivial such asreturn value;
and so assigning it inside the loop would be no more expensive than outside the loop after the JIT compiler inlines the code.
然而,更多重要的是两者之间的语义差异及其在多线程环境中可能产生的影响:如果对象的状态 example
以导致<$ c $的方式发生变化c> example.getValue()要返回对不同对象的引用,有可能在每次迭代中,方法 doSomething(Object object)
实际上将通过直接调用 doSomething(example.getValue());
来操作 Object
的不同实例。另一方面,通过在循环外调用getter并设置对返回实例的引用( Object object = example.getValue();
), doSomething(object);
将对 n 迭代的对象
n 时间进行操作。
However, more important is the difference in semantics between the two and its possible effects in a multi-threaded environment: If the state of the object example
changes in a way which causes example.getValue()
to return references to different objects, it is possible that, in each iteration, the method doSomething(Object object)
will actually operate on a different instance of Object
by directly calling doSomething(example.getValue());
. On the other hand, by calling a getter outside the loop and setting a reference to the returned instance (Object object = example.getValue();
), doSomething(object);
will operate on object
n times for n iterations.
这种语义差异可能导致多线程环境中的行为与单线程环境中的行为完全不同。此外,这不一定是实际的内存中多线程问题:如果 example.getValue()
取决于例如数据库/ HDD /网络资源,这些数据可能在循环执行期间发生变化,即使Java应用程序本身是单线程的,也可能返回不同的对象。出于这个原因,最好考虑你实际想要用循环完成什么,然后选择最能反映预期行为的选项。
This difference in semantics can cause behavior in a multi-threaded environment to be radically different from that in a single-threaded environment. Moreover, this need not be an actual "in-memory" multi-threading issue: If example.getValue()
depends on e.g. database/HDD/network resources, it is possible that this data changes during execution of the loop, making it possible that a different object is returned even if the Java application itself is single-threaded. For this reason, it is best to consider what you actually want to accomplish with your loop and to then choose the option which best reflects the intended behavior.
这篇关于Java在for循环中使用getter还是创建局部变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!