【问题标题】:In Java, is assigning reference slower than assigning primitive types? Why?在Java中,分配引用比分配原始类型慢吗?为什么?
【发布时间】:2017-10-19 03:52:20
【问题描述】:

我编写了测试来确定与分配原始类型值相比,分配引用是更慢还是同样快,我的结果是,分配引用要慢得多。

@Test
public void testPassReference(){
    long count = 0;
    DoublyLinkedNodeNoGetter node1 = linkedList.head;
    DoublyLinkedNodeNoGetter[] nodes = new DoublyLinkedNodeNoGetter[2];
    nodes[0] = linkedList.head.next;
    nodes[1] = linkedList.head.next.next;
    while(count++<10000000000l){
        node1 = nodes[(int)(count%2)];
    }
}

@Test
public void testPassValue(){
    long i = 0;
    long j = 0;
    while(i++<10000000000l){
        j = i%2;
    }

结果:

testPassReference:8s 934ms

testPassValue: 2s 707ms

我很困惑,因为根据我的理解,当使用'='分配一个对象时,这意味着将引用(即地址)从一个对象转移到另一个对象。即使在 64 位系统中,引用的长度也应该是 64 位,也就是原始类型“long”的长度。因此,为什么分配参考如此缓慢?在我们将引用分配给另一个时发生了什么?

感谢您的帮助! 谢谢!

更新:

感谢cmets!

我的测试方法存在缺陷。我还在考虑如何为他们两个做一个公平的测试。 T.T

那么,别说测试了,理论上这两种作业有什么区别吗?

更新2:

@Test
public void testPassReference(){
    long count = 0;
    DoublyLinkedNodeNoGetter node1 = linkedList.head;
    DoublyLinkedNodeNoGetter[] nodes = new DoublyLinkedNodeNoGetter[2];
    nodes[0] = linkedList.head.next;
    nodes[1] = linkedList.head.next.next;
    while(count++<10000000000l){
        node1 = nodes[(int)(count%2)];
    }
}

@Test
public void testPassValue(){
    long i = 0;
    long[] j = {1,2};
    long k;
    while(i++<10000000000l){
        k = j[(int)(i%2)];
    }
}

我再次重新设计了测试,现在我得到了类似的结果。所以我认为赋值类型对操作性能影响不大。

testPassReference:9s 5ms

testPassValue: 9s 4ms

【问题讨论】:

  • 在紧密循环中,JVM 的 JIT 编译器将进行大量优化,因此任何测量都将非常不可靠。 (请发布文本,而不是文本图像的链接!)
  • 您的引用测试代码不仅是一个赋值,也是一个方法调用。您正在将苹果与梨进行比较。
  • @KenY-N 您好,感谢您的回复。我已经用文字更新了所有内容。给您带来的不便,我们深表歉意。
  • @UsagiMiyamoto 没有。引用是 one 指针,指向对象。该对象包含自己的类指针。
  • 数组查找需要一些时间。你还有苹果和梨。

标签: java algorithm performance jvm


【解决方案1】:

从某种意义上说,JVM 可以为int 操作优化代码而变得更慢,尤其是如果您有一个不做任何事情的微基准测试并且 JVM 可以轻松检测到这一点。

但是,在这两种情况下,它都是一个 32 位的赋值(除非您有一个带有 64 位引用的大堆),所以底层的工作是相同的。

顺便说一句,您很可能正在对 %2 或您的阵列访问的成本进行基准测试,因为这些成本可能要高出一个数量级。

【讨论】:

    【解决方案2】:

    您的基准测试完全错误。 您不会对代码进行预热,也不会检查DCE 以及许多其他事情。 查看JMH,但您需要了解许多事情才能编写正确的基准。 你可以看看这个answer作为例子。

    【讨论】:

      猜你喜欢
      • 2013-05-10
      • 1970-01-01
      • 2016-04-29
      • 2015-12-24
      • 2014-07-06
      • 1970-01-01
      • 2014-01-18
      • 2016-10-08
      • 1970-01-01
      相关资源
      最近更新 更多