在java,为什么会慢?

In java, why is it slow?

我定义了一个 class 信息:

    public static class Node {
        Node prev;
        public Node() {
        }
        public Node(Node prev) {
            this.prev = prev;
        }
    }

测试用例 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);
    }

对于上面的测试用例,我的机器完成需要纳秒8434100 -> 0.008 秒

测试用例 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);
    }

在上面的例子中,我将创建一个存储变量last来存储最后一个node对象。

对于上面的测试用例,我的机器完成需要纳秒9522600 -> 0.009 秒

测试用例 3 :

在这种情况下发生突变。

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

案例 3,与案例 2 非常相似,但我会将 last 对象传递给 Nodeconstructor。 对于上面的测试用例,我的机器完成需要纳秒 933890100 -> 0.9 秒。

令人惊讶的是,它慢了 100 倍。

测试用例 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);
    }

在案例 4 中,我有一个 list 存储 newNode 列表。 对于上面的测试用例,我的机器完成需要纳秒 360559900 -> 0.3 秒。 比case 3快。java重新优化了吗?

问题

你知道为什么这么慢吗?请让我知道。我已经研究和阅读了很多但还没有答案

两个问题:

  1. 作为, microbenchmarks are misleading. More in this question's answers: How do I write a correct micro-benchmark in Java?

  2. 但也有可能:因为在情况 1 和情况 2 中,您不会在内存中建立一千万个 Node 个对象,您在任何给定时间最多有两个。在进行过程中,您将释放以前的节点。但是在情况 3 中,您保留了您曾经创建的所有 Node 个对象,因此您最终会在内存中拥有一千万个小对象。这在内存管理方面需要大量开销,显着减慢速度。