I have defined a class with information:
public static class Node {
Node prev;
public Node() {
}
public Node(Node prev) {
this.prev = prev;
}
}
Test case 1 :
@Test
public void test1() {
long start = System.nanoTime();
for (int i = 0; i < 10_000_000; i ) {
Node newNode = new Node();
}
long timeRun = System.nanoTime() - start;
System.out.println("nanoTime: " timeRun);
}
For the above test case, my machine complete needs nanoseconds 8434100
-> 0.008 second
Test case 2 :
@Test
public void test() {
Node last = null;
long start = System.nanoTime();
for (int i = 0; i < 10_000_000; i ) {
Node newNode = new Node();
last = newNode ;
}
long timeRun = System.nanoTime() - start;
System.out.println("nanoTime: " timeRun);
}
In the above case, I will create a storage variable last
to store the last node
object.
For the above test case, my machine complete needs nanoseconds 9522600
-> 0.009 second
Test case 3 :
Mutation in this case.
@Test
public void test() {
Node last = null;
long start = System.nanoTime();
for (int i = 0; i < 10_000_000; i ) {
Node newNode = new Node(last);
last = newNode ;
}
long timeRun = System.nanoTime() - start;
System.out.println("nanoTime: " timeRun);
}
Case 3, quite similar to case 2 but I will pass last
object to constructor
of Node
.
For the above test case, my machine complete needs nanoseconds 933890100
-> 0.9 second.
Amazingly, it's 100 times slower.
Test case 4 :
@Test
public void test() {
List<Node> list = new ArrayList<>();
Node last = null;
long start = System.nanoTime();
for (int i = 0; i < 10_000_000; i ) {
Node newNode = new Node(last);
list.add(newNode);
last = newNode ;
}
long timeRun = System.nanoTime() - start;
System.out.println("nanoTime: " timeRun);
}
In case 4, I had a list
to store newNode
to list.
For the above test case, my machine complete needs nanoseconds 360559900
-> 0.3 second.
It is faster than case 3. Did java re-optimize it?
Questions
Do you know why it's slow? please let me know. I have researched and read a lot but no answer yet
CodePudding user response:
Two issues:
As Dave Newton said, microbenchmarks are misleading. More in this question's answers: How do I write a correct micro-benchmark in Java?
But also probably: Because in cases 1 and 2, you don't build up ten million
Node
objects in memory, you have at most two at any given time. As you're going along, you release previous nodes. But in case 3, you keep all theNode
objects you ever create, so you end up with ten million small objects in memory. That requires a lot of overhead in terms of memory management, slowing things down markedly.