我对指令优化有疑问。如果要在两个语句中使用一个对象,创建一个新的对象引用会更快,还是应该直接在两个语句中调用该对象?
出于我的问题的目的,该对象是Vector
个对象的一部分(此示例来自没有ArrayLists的Java的简化版本)。这是一个例子:
AutoEvent ptr = ((AutoEvent)e_autoSequence.elementAt(currentEventIndex));
if(ptr.exitConditionMet()) {currentEventIndex++; return;}
ptr.registerSingleEvent();
AutoEvent
是有问题的类,e_autoSequence
是AutoEvent对象的Vector
。 AutoEvent
包含两个有问题的方法:exitConditionMet()
和registerSingleEvent()
。
因此,此代码可以替换为:
if(((AutoEvent)e_autoSequence.elementAt(currentEventIndex)).exitConditionMet())
{currentEventIndex++; return;}
((AutoEvent)e_autoSequence.elementAt(currentEventIndex)).registerSingleEvent();
这比上面的更快吗?
我理解投射过程很慢,所以这个问题实际上是双重的:另外,如果我没有投射对象,那么会更加高度优化?
请记住,这仅用于对象的两种用途。
答案 0 :(得分:2)
第一种解决方案全面改善:
elementAt
方法。这实际上是这里最昂贵的操作,所以只做一次就是一场不错的表现。同样做两次可能会让你达到一些竞争条件。ptr
)非常便宜并且通常是免费的 - Java JIT编译器足够智能在这里生成高度优化的代码。 P.S。 Vector
已经过时了。考虑转换为ArrayList<AutoEvent>
。通过使用通用ArrayList,您不需要显式转换,它比Vector
快得多(因为它不同步,因此锁定开销较小)
答案 1 :(得分:0)
第一种解决方案会更快。
原因是赋值比方法调用工作得更快。 在第二种情况下,你将调用方法elementAt()两次,这会使它变慢,JVM可能无法优化这段代码,因为它不知道elementAt()究竟发生了什么。
还要记住,Vector的方法是同步的,这使得每次方法调用都会因锁定获取而变慢。
答案 2 :(得分:0)
我不知道这里的“创建一个新的对象引用”是什么意思。以下代码((AutoEvent)e_autoSequence.elementAt(currentEventIndex))
可能会被转换为获取序列元素的字节码,将其强制转换为AutoEven
并将结果引用存储在堆栈中。局部变量ptr
作为其他局部变量也存储在堆栈中,因此分配对is的引用只是将4个字节从一个堆栈槽复制到另一个堆栈槽。这是非常非常快的操作。现代JVM不进行引用计数,因此分配引用可能与分配int
值一样便宜。
答案 3 :(得分:0)
让我们先得到一些术语。您的代码不会“创建新的对象引用”。它从Vector
获取现有对象引用(一次或两次)。
要回答你的问题,获取一次并将引用放入临时变量(可能)要快一点。但差别很小,不太可能显着,除非你在循环中多次这样做。
(elementAt
或Vector
上的ArrayList
方法O(1)
且价格便宜。如果列表是一个链接列表,其实现O(N)
对于elementAt
,然后该调用可能很昂贵,并且进行1或2次调用之间的差异可能很大......)
一般来说,您应该考虑算法的复杂性,但除此之外,您不应该花时间优化...直到您有可靠的分析证据来告诉您优化的位置。
我不能说ArrayList
是否更合适。这可能是您需要 Vector
提供的线程安全的情况。