【问题标题】:Why the first call to constructor takes 10 times more time than other ones?为什么第一次调用构造函数花费的时间是其他调用的 10 倍?
【发布时间】:2012-08-14 06:58:51
【问题描述】:
class testx
{
  public testx()
  {
    long startTime = System.nanoTime();
    System.out.println((System.nanoTime() - startTime));
  }

  public static void main(String args[])
  {
      new testx();
      new testx();
      new testx();
  }
}

我总是得到类似于7806 660 517 的结果。为什么第一次调用的时间是其他调用的 10 倍?

【问题讨论】:

    标签: java performance time nanotime


    【解决方案1】:

    这绝对是 Louis Wasserman,它在第一轮需要更长的时间,因为它必须加载所有必要的 System 类,你可以通过在创建类的新实例之前调用空白 println() 来解决这个问题,因为看看当我们这样做时会发生什么:

    public class testx
    {
      public testx()
      {
        long startTime = System.nanoTime();
        System.out.println((System.nanoTime() - startTime));
      }
    
      public static void main(String args[])
      {
        //loads all System.* classes before calling constructor to decrease time it takes
        System.out.println();
          new testx();
          new testx();
          new testx();
      }
    }
    

    输出:

    405 0 405

    初始代码的输出位置:

    7293 0 405

    【讨论】:

      【解决方案2】:

      因为 JVM 在那个时候第一次加载了一堆 o' 类。一旦第一个System.nanoTime() 返回,您已经加载了System.classtestx.class,但是一旦System.out.println 出现,我怀疑很多I/O 类都被加载了,这需要一些时间。

      无论如何,这不是一个好的基准测试技术;在开始测量之前,您真的应该通过运行约 10000 次迭代来预热 JIT。或者(并且最好)使用预先构建的基准测试工具,例如 Caliper

      【讨论】:

      • 在运行main之前不会加载吗?
      • 这行执行的时候是不是已经加载了long startTime = System.nanoTime();
      • 对不起,你说得对。 testx.class 已经加载了,但是第一次调用 System.out.println 时,JVM 几乎肯定需要将更多的类加载到内存中。
      • 使用调试器逐步完成并对其进行分析。你会得到答案的。
      • @LouisWasserman 在今天的情况下,很可能所有这些类都已加载,但未初始化,因为 JLS 定义了精确的语义初始化类的确切时刻。这不会颠覆你的主要观点,只是澄清它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      • 1970-01-01
      • 2022-07-05
      • 2013-12-11
      • 1970-01-01
      相关资源
      最近更新 更多