2

我有一个关于指令优化的问题。如果要在两个语句中使用一个对象,创建一个新的对象引用会更快还是应该在两个语句中直接调用该对象?

就我的问题而言,该对象是对象的一部分Vector(此示例来自没有 ArrayLists 的简化版 Java)。这是一个例子:

AutoEvent ptr = ((AutoEvent)e_autoSequence.elementAt(currentEventIndex));
if(ptr.exitConditionMet()) {currentEventIndex++; return;}
ptr.registerSingleEvent();

AutoEvent是有问题的类,e_autoSequenceVectorAutoEvent 对象的。包含有问题的AutoEvent两种方法:exitConditionMet()registerSingleEvent().

因此,此代码可以交替编写为:

if(((AutoEvent)e_autoSequence.elementAt(currentEventIndex)).exitConditionMet()) 
    {currentEventIndex++; return;}
((AutoEvent)e_autoSequence.elementAt(currentEventIndex)).registerSingleEvent();

这比上面的快吗?

我知道铸造过程很慢,所以这个问题实际上是双重的:另外,如果我不铸造对象,哪个会更优化?

请记住,这仅用于所讨论对象的两种用途。

4

4 回答 4

2

第一个解决方案在所有方面都更好:

  • 只调用一次向量elementAt方法。这实际上是这里最昂贵的操作,所以只做一次就是一个不错的性能胜利。同样做两次可能会使您面临一些竞争条件。
  • 只有一次铸造操作。在现代 JVM 上强制转换非常便宜,但仍然有一点成本。
  • 恕我直言,它更具可读性。你得到一个对象,然后用它做两件事。如果你得到了两次,那么读者必须在心里弄清楚你得到的是同一个对象。最好得到一次,并将其分配给具有好名称的变量。
  • 局部变量的单个赋值(如ptr第一个解决方案中)非常便宜且通常免费- Java JIT 编译器足够聪明,可以在这里生成高度优化的代码。

PSVector已经过时了。考虑转换为ArrayList<AutoEvent>. 通过使用通用 ArrayList,您无需显式强制转换,而且它比 a 快得多Vector(因为它不同步,因此锁定开销更少)

于 2013-02-12T04:33:51.027 回答
0

第一个解决方案会更快。

原因是赋值比方法调用工作得更快。在第二种情况下,您将调用 elementAt() 方法两次,这将使其变慢,并且 JVM 可能无法优化此代码,因为它不知道 elementAt() 中究竟发生了什么。

还要记住,Vector 的方法是同步的,这使得每个方法调用由于获取锁而变得更慢。

于 2013-02-12T04:06:44.150 回答
0

我不知道这里的“创建新对象引用”是什么意思。下面的代码((AutoEvent)e_autoSequence.elementAt(currentEventIndex))可能会被翻译成字节码,获取序列元素,将其转换为AutoEven并将结果引用存储在堆栈中。与其他局部变量ptr一样的局部变量也存储在堆栈中,因此分配对 is 的引用只是将 4 个字节从一个堆栈槽复制到另一个附近的堆栈槽。这是非常非常快速的操作。现代 JVM 不进行引用计数,因此分配引用可能与分配int值一样便宜。

于 2013-02-12T04:17:57.600 回答
0

让我们先弄清楚一些术语。您的代码不会“创建新的对象引用”。它正在从Vector.


要回答您的问题,获取一次并将引用放入临时变量(可能)会快一点。但是差异很小,除非您在循环中多次执行此操作,否则不太可能显着。

(orelementAt上的方法很便宜。如果列表是一个链表,它有一个实现 for ,那么该调用可能很昂贵,并且进行 1 次或 2 次调用之间的差异可能很大......)VectorArrayListO(1)O(N)elementAt

一般来说,您应该考虑算法的复杂性,但除此之外,您不应该花时间优化......直到您有可靠的分析证据告诉您在哪里优化。


我不能说是否ArrayList更合适。这可能是您需要Vector.

于 2013-02-12T04:39:34.380 回答