方法执行错误的时间

时间:2011-12-19 07:27:29

标签: java performance execution

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

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的代码段之间更改位置,我会得到不同的时间! 如果我把通用的循环(带有时间打印的课程)放在简单的下面,我会得到更好的通用时间,如果我把简单放在通用下面,我会更好的时间来简单!

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

4 个答案:

答案 0 :(得分:1)

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

您应该进行以下修改:

  1. 首先运行两个不定时的测试,然后重新运行它们,以免受到JIT的影响。
  2. 您应该使用System.nanoTime(),因为这对于计时更准确(您永远不应该得到0的差异)。
  3. 您还应该测试一些空方法,因为您还要在每个循环中对字符串连接操作进行计时。
  4. 另请注意,在Java中,泛型类型已擦除,因此根本不存在运行时差异。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

在第二轮比赛中你的内存也增加了两倍。有各种各样的变量可以影响这个测试。

答案 3 :(得分:0)

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