【问题标题】:Wrong time of method execution方法执行时间错误
【发布时间】:2011-12-19 07:27:29
【问题描述】:

我想测试在简单通用的hashmap中添加和获取item的时间:

public void TestHashGeneric(){


        Map hashsimple = new HashMap();             

        long startTime = System.currentTimeMillis();



        for (int i = 0; i < 100000; i++) {
            hashsimple.put("key"+i, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" );
        }

        for (int i = 0; i < 100000; i++) {
            String ret =(String)hashsimple.get("key"+i);
        }
        long endTime =System.currentTimeMillis();

        System.out.println("Hash Time " + (endTime - startTime) + " millisec");

        Map<String,String> hm = new HashMap<String,String>();

        startTime =  System.currentTimeMillis();



        for (int i = 0; i < 100000; i++) {
            hm.put("key"+i, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" );
        }

        for (int i = 0; i < 100000; i++) {
            String ret = hm.get("key"+i);
        }
        endTime = System.currentTimeMillis();

        System.out.println("Hash generic Time " + (endTime - startTime) + " millisec");         

    }

问题是,如果我在 hashmap 的代码部分之间改变位置,我会得到不同的时间! 如果我将泛型的循环(当然还有时间打印)放在简单的下面,我会得到更好的泛型时间,如果我把简单放在泛型之下,我会得到更好的简单时间!

如果我为此使用不同的方法,也会发生同样的情况。

【问题讨论】:

  • 请编辑您的问题,使其更有意义 - 目前很难理解。请阅读tinyurl.com/so-hints
  • 问题不清楚。您是说您有两段据称完全不相关的代码,而第二段运行的代码运行得更快(相反,当您切换它们的顺序时)?可能是 JIT 在工作等。也许“热身”这两个部分并在完成后进行计时。
  • 但我可以告诉你:泛型对运行时性能的影响为零。它们是纯编译时的东西。
  • 泛型对运行时性能的影响为零?谢谢!

标签: java performance execution


【解决方案1】:

JIT 将在程序运行时编译和优化您的程序,因此第二次运行总是更快。

您应该进行以下修改:

  1. 先不定时运行两个测试,然后定时重新运行它们,以免受到 JIT 的影响。
  2. 您应该使用System.nanoTime(),因为这对于计时更准确(您永远不应该得到 0 的差异)。
  3. 您还应该针对一些空方法进行测试,因为您还在每个循环中对字符串连接操作进行计时。

还要注意,Java 中的泛型类型被擦除,因此根本不存在运行时差异。

【讨论】:

    【解决方案2】:

    当您有一个达到编译阈值(大​​约 10K)的循环时,整个方法都会被编译。这可以使第一个循环看起来更快(因为它被正确优化,因为第二个循环没有计数器信息)或第二个循环出现在之后(因为它甚至在它开始之前编译)

    解决这个问题的最简单方法是将每个测试放在自己的方法中,它们将被独立编译和优化。 (顺序仍然很重要,但不太重要)我仍然建议多次运行测试以查看结果如何变化。

    【讨论】:

      【解决方案3】:

      Java 运行时非常复杂 - 它在运行时会进行一些学习/优化。您可以通过首先“预热”JVM 来获得所需的测试。尝试调用TestHashGeneric() 两次,看看第二组结果会给你什么。

      第二次运行时,内存中的内容也增加了一倍。有各种各样的变量会影响这个测试。

      【讨论】:

        【解决方案4】:

        这不是执行微基准测试的正确方法,因为它非常复杂 (Why?)。我建议你为此使用Caliper 框架。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-04-27
          • 2015-08-10
          • 1970-01-01
          • 1970-01-01
          • 2018-07-14
          • 2015-10-26
          • 1970-01-01
          相关资源
          最近更新 更多