[SOLVED] In java, why is it slow?

Issue

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

Solution

Two issues:

  1. As Dave Newton said, microbenchmarks are misleading. More in this question’s answers: How do I write a correct micro-benchmark in Java?

  2. 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 the Node 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.

Answered By – T.J. Crowder

Answer Checked By – David Marino (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *