在Java中,分配引用比分配原始类型要慢吗?为什么?

时间:2017-10-19 03:52:20

标签: java algorithm performance jvm

我编写测试来确定与分配基元类型值相比,分配引用是否更慢或同样快,而我的结果是,分配引用要慢得多。

@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”的长度。那么为什么分配参考是如此之慢?在我们将引用分配给另一个时发生了什么?

感谢您的帮助! 谢谢!

更新:

感谢您的评论!

我的测试方法存在缺陷。我还在考虑如何对它们进行公平的测试。 T.T

那么,忘了测试,理论上这两种作业有什么不同吗?

UPDATE2:

@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

2 个答案:

答案 0 :(得分:0)

从某种意义上说,JVM可以做更多的技巧来优化int操作的代码,尤其是如果你有一个微型基准测试没有做任何事情而且JVM可以很容易地检测到它。

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

BTW很可能是您对%2或您的阵列访问费用进行基准测试,因为这些费用可能更贵。

答案 1 :(得分:0)

您的基准测试完全错误。 你不会让你的代码变暖,你不会检查DCE和许多其他事情。 看看JMH,但是你需要了解很多东西才能写出正确的基准。 您可以查看此answer作为示例。