-4

I wrote tests to figure out that whether assigning references is slower or equally fast compared with assigning primitive types values, and my result is, assigning references is much slower.

@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;
    }

And the result:

testPassReference: 8s 934ms

testPassValue: 2s 707ms

I am confused because from my understanding, when assign an Object using '=', it means transfer the reference, which is the address, from one object to the other one. Even in the 64 bit system, the reference should be 64 bit in length, which is the length of the primitive type 'long'. Thus why assigning a reference is so slow? What happened during we assign a reference to another?

I would be appreciate for your help! Thank you!

UPDATE:

Thanks for the comments!

There are defects in my test approach. I am still thinking about how to make a fair test for both of them. T.T

So, forget about the test, theoretically is there any difference in the two kinds of assignment?

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)];
    }
}

Again I re-designed the tests and now I get similar result. So I think the type of assignments has few effects on the performance of operation.

testPassReference: 9s 5ms

testPassValue: 9s 4ms

  • 3
    On tight loops like that the JVM's JIT compiler is going to optimise heavily, so any measure is going to be highly unreliable. (And please post text, not links to images of text!) – Ken Y-N Oct 19 '17 at 03:55
  • 3
    Your test code for references does not only an assignment but also a method call. You are comparing apples with pears. – Henry Oct 19 '17 at 03:56
  • @KenY-N Hi, thanks for your response. I have updated everything with text. Sorry for any inconvenience. – Zhijie Cui Oct 19 '17 at 04:09
  • Also, objecr assignment is not just a copying of a pointer... References are at least 2 pointers: one for the value object, and another for the `class` object. Object assignment also does some type checking... – Usagi Miyamoto Oct 19 '17 at 04:10
  • @Henry Hi, thanks for your response! I have re-design the test and removed the method call. And I tested the method along, it takes about 6s, which is one third of the total elapsed time. – Zhijie Cui Oct 19 '17 at 04:10
  • 1
    @UsagiMiyamoto No. References are *one* pointer, to the object. The object contains its own class pointer. – user207421 Oct 19 '17 at 04:11
  • @UsagiMiyamoto Got it! Thanks a lot. – Zhijie Cui Oct 19 '17 at 04:11
  • 3
    The array lookup is going to take some time. You've still got apples and pears. – Dawood ibn Kareem Oct 19 '17 at 04:12
  • @DawoodibnKareem Thanks. I'll think about it. – Zhijie Cui Oct 19 '17 at 04:15
  • beware of [microbenchmarking pitfalls](https://stackoverflow.com/q/504103/1362755) – the8472 Oct 19 '17 at 20:55

2 Answers2

0

It's slower in the sense that the JVM can do more tricks to optimise code away for int operations, esp if you have a micro-benchmark which doesn't do anything and the JVM can easily detect that.

However, in both cases it's a 32-bit assignment (unless you have a large heap with 64-bit references) so the underlying work is the same.

BTW most likely you are benchmarking the cost of your %2 or your array access as these can be an order magnitude more expensive.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

Your benchmark is completely wrong. You don't make warming your code, you don't check DCE, and many other things. Look at JMH, but you need to understand many things for writing a correct benchmark. You can look at this answer as an example.