【问题标题】:inconsistent results when timing a process对过程进行计时时结果不一致
【发布时间】:2012-03-22 21:09:27
【问题描述】:

我正在尝试使用System.currentTimeMillis()(或System.nanoTime())来计时我的程序的性能,我注意到每次运行它时 - 它给出的完成时间的结果不同任务。

即使是简单的测试:

long totalTime;
long startTime;
long endTime;
startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++)
{
    for (int j = 0; j < 1000000000; j++)
    {
    }
}
endTime = System.currentTimeMillis();
totalTime = endTime-startTime;
System.out.println("Time: " + totalTime);

产生各种不同的输出,从 0 到 200。谁能说出我做错了什么或提出替代解决方案?

【问题讨论】:

    标签: java performance timing


    【解决方案1】:

    循环不执行任何操作,因此您正在计时检测循环所需的时间是没有意义的。

    更准确地定时循环不会有帮助,您需要做一些稍微有用的事情来获得可重复的结果。

    如果您在 32 位 Windows 上运行,我建议您尝试 -server

    十亿个时钟周期大约需要 10 年,因此它并没有真正迭代那么多次。

    【讨论】:

    • +1 对于计算,十年的近似值不会那么糟糕。我计算了 13 年的 2.4GHz CPU,单线程。
    • +1 我认为 Peter 低估了事情的严重性。我最近做了一些基准测试,JVM 现在有一个即时优化器,它可以快速发现您将检查的数组元素并only 填充这些元素。我怀疑它与您可能尝试和使用的任何随机数生成器有勾结。我也认为它知道你是否在看屏幕。祝你好运,试图欺骗它做一些实际的工作。
    • 最初我正在做一些事情,我正在实现三种不同的贪心算法(第一次拟合、下一次拟合和最佳拟合)并计时它们的性能。问题是,有时最佳拟合的执行速度比其他两个都快,有时第一次拟合可以做到这一点并且没有任何意义(尽管这些算法的代码似乎是正确的)。
    • 您需要将每个循环放在单独的方法中,忽略预热时间,并确保运行基准测试至少 2 秒。
    • 如果您必须进行自己的基准测试——这并不总是一个好主意——然后运行方法不计时几秒钟,然后只有这样才做计时。您必须给 JIT 时间进行优化。
    【解决方案2】:

    这正是预期的行为——当您重新运行计时时,它应该会变得更快。当您多次重新运行一个方法时,JIT 会花费更多精力将其编译为本机代码并对其进行优化;我希望在运行这段代码足够长的时间后,JIT 会完全消除循环,因为它实际上并没有做任何事情。

    在 Java 代码上获得精确基准测试的最佳和最简单的方法是使用像 Caliper 这样的工具来“预热”JIT 以鼓励它全面优化您的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多