我想测试在简单和通用的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的代码段之间更改位置,我会得到不同的时间! 如果我把通用的循环(带有时间打印的课程)放在简单的下面,我会得到更好的通用时间,如果我把简单放在通用下面,我会更好的时间来简单!
如果我使用不同的方法,也会发生同样的情况。
答案 0 :(得分:1)
JIT将在程序运行时编译和优化您的程序,因此第二次运行将始终更快。
您应该进行以下修改:
System.nanoTime()
,因为这对于计时更准确(您永远不应该得到0的差异)。另请注意,在Java中,泛型类型已擦除,因此根本不存在运行时差异。
答案 1 :(得分:1)
如果您有一个达到编译阈值(大约10K)的循环,则编译整个方法。这可以使第一个循环看起来更快(因为它被正确优化,因为第二个循环没有计数器信息)或第二个循环出现之后(因为它在它甚至开始之前编译)
解决这个问题的最简单方法是将每个测试放在自己的方法中,并且它们将被独立编译和优化。 (顺序仍然重要,但不太重要)我仍然建议多次运行测试以查看结果如何变化。
答案 2 :(得分:0)
Java Runtime非常复杂 - 它在运行时会进行一些学习/优化。您可以通过首先“预热”JVM来获得所需的测试。尝试两次调用TestHashGeneric()
,看看第二组结果会给你什么。
在第二轮比赛中你的内存也增加了两倍。有各种各样的变量可以影响这个测试。
答案 3 :(得分:0)