当前位置: 首页 > 面试题库 >

第一次Java循环运行缓慢,为什么?[Sun HotSpot 1.5,sparc]

仲孙文乐
2023-03-14
问题内容

在Solaris SPARC机器上对一些Java代码进行基准测试时,我注意到我第一次调用该基准测试函数时,它运行EXTREMELY的速度很慢(相差10倍):

  • 第一| 1 | 25295.979毫秒
  • 第二| 1 | 2256.990毫秒
  • 第三 1 | 2250.575毫秒

为什么是这样?我怀疑是JIT编译器,有什么办法可以验证这一点?

编辑:
根据一些答案,我想澄清一下这段代码是我可以发现表现出这种行为的最简单的测试用例。因此,我的目标不是让它快速运行,而是了解正在发生的事情,以便在实际基准测试中避免它。

解决: Tom Hawtin正确地指出我的“慢”时间实际上是合理的。遵循此观察,我将调试器附加到Java进程。在第一阶段,内部循环如下所示:

0xf9037218:     cmp      %l0, 100
0xf903721c:     bge,pn   %icc,0xf90371f4        ! 0xf90371f4
0xf9037220:     nop
0xf9037224:     ld       [%l3 + 92], %l2
0xf9037228:     ld       [%l2 + 8], %l6
0xf903722c:     add      %l6, 1, %l5
0xf9037230:     st       %l5, [%l2 + 8]
0xf9037234:     inc      %l0
0xf9037238:     ld       [%l1], %g0
0xf903723c:     ba,pt    %icc,0xf9037218        ! 0xf9037218

在以下迭代中,循环如下所示:

0xf90377d4:     sub      %l2, %l0, %l3
0xf90377d8:     add      %l3, %l0, %l2
0xf90377dc:     add      %l2, 1, %l4
0xf90377e0:     inc      %l0
0xf90377e4:     cmp      %l0, 100
0xf90377e8:     bl,pn    %icc,0xf90377d8        ! 0xf90377d8

因此,HotSpot从内部循环中删除了内存访问,从而将其加速了一个数量级。

课: 做数学!我本来应该做汤姆的计算的。

基准Java代码:

    private int counter;
    private int nThreads;

    private void measure(String tag) throws Exception {
            MyThread threads[] = new MyThread[nThreads];
            int i;

            counter = 0;

            for (i = 0; i < nThreads; i++)
                    threads[i] = new MyThread();

            long start = System.nanoTime();

            for (i = 0; i < nThreads; i++)
                    threads[i].start();

            for (i = 0; i < nThreads; i++)
                    threads[i].join();

            if (tag != null)
                    System.out.format("%-20s | %-2d | %.3f ms \n", tag, nThreads,
                                     new Double((System.nanoTime() - start) / 1000000.0));
    }
    public MyBench() {
            try {
                    this.nThreads = 1;
                    measure("First");
                    measure("Second");
                    measure("Third");
            } catch (Exception e) {
                    System.out.println("Error: " + e);
            }
    }

    private class MyThread extends Thread {
            public void run() {
                    while (counter < 10000000) {
                            // work
                            for (int j = 0; j < 100; j++)
                                    counter++;
                            counter -= 99;
                    }
            }
    }

问题答案:

一些丑陋,不切实际的代码(微基准测试的内容):

                while (counter < 10000000) {
                        // work
                        for (int j = 0; j < 100; j++)
                                counter++;
                        counter -= 99;
                }

因此,这是做什么的,应该运行多快。

内部循环将计数器递增100次,然后将计数器递减99。因此递增1。注意counter是外部类的成员变量,因此存在一些开销。然后运行10,000,000次。因此,内部循环运行了1,000,000,000次。

使用访问器方法的循环,称为25个循环。在1 GHz下有1,000,000,000次,给出25s。

嘿,我们预测了 缓慢的 时间。慢的时间很快。最快的时间是基准测试以某种方式打破之后-迭代2.5个周期?使用-
server,您可能会发现它变得更加愚蠢。



 类似资料:
  • 我在玩node.js,我发现这个简单的程序运行得非常慢,我甚至没有等看它在3分钟后花了多长时间。 我使用不同的值进行了实验,发现1-112050需要3秒,而1-112051需要一分钟。这种突然的下降很奇怪。python中的相同程序或等效的shell脚本“seq 1 112051”在合理的时间内(0-2秒)运行。 请注意,此节点。js应用程序运行速度更快: 谁能给我解释一下为什么是node。js的行

  • 编辑:为什么在局部变量上这么快?(~16秒进行相同的迭代,但对函数内部的局部变量进行迭代)

  • 我在pyplay上做了一个Tamagotchi项目,在这个早期阶段,程序运行非常缓慢。你对原因有什么提示吗?还有,有没有办法加快速度? 到目前为止,这是我的代码:

  • 问题内容: 和别的: 两者都不起作用(强制关闭应用程序)。我可以尝试其他哪些选择? 问题答案: 您的代码失败,因为您在后台线程中执行睡眠,但是显示数据必须在UI线程中执行。 您必须从runOnUiThread(Runnable)运行displayData或定义处理程序并将消息发送给它。 例如:

  • 我发现这样的php代码: 我希望这个循环会执行4次,因为$I变成了对$的引用(对吗?)。然而,循环只执行一次,并输出: a=10,i=10 我不明白为什么它会这样工作。有什么想法吗?

  • 我对python中双for循环的使用感到困惑,这是我的代码: 输出如下: 它只对外循环的第一个值执行内循环,为什么会发生这种情况?我怎样才能让它在第一个和第二个变量的所有组合上循环?