我试图测量不同类型的集合上不同操作的时间,并想对它们进行比较,但是在相同类型的集合上,我得到的值差别很大,比如因子 1000。我使用了常用的技术在这里阅读:How do I time a method's execution in Java?
我比较了Hashset、TreeSet和LinkedHashSet。 我用 1 000 000 个整数填充集合,使用 contains() 方法并迭代集合。我测量了每次操作的时间,值相差很大。因此,我使用相同类型的新集第二次执行此操作,并且我得到的执行时间似乎不合法。
相同类型的集合需要1400毫秒然后300毫秒才能被填充。这是为什么?
这是一个代码示例,它可能会让我的意思更清楚:
public static void main(String[] args){
HashSet<Integer> firstHashSet = new HashSet<>(predefinedSize);
HashSet<Integer> secondHashSet = new HashSet<>(predefinedSize);
LinkedHashSet<Integer> firstLinkedHashSet = new LinkedHashSet<>(predefinedSize);
LinkedHashSet<Integer> secondLinkedHashSet = new LinkedHashSet<>(predefinedSize);
TreeSet<Integer> firstTreeSet = new TreeSet<>();
TreeSet<Integer> secondTreeSet = new TreeSet<>();
int x = 9432;
System.out.println("filling hashSet: <" + fillSet(firstHashSet) + "> milliSeconds");
System.out.println("filling linkedSet: <" + fillSet(firstLinkedHashSet) + "> milliSeconds");
System.out.println("filling treeSet: <" + fillSet(firstTreeSet) + "> milliSeconds");
System.out.println("-------------------------------------------------------------");
System.out.println("filling hashSet: <" + fillSet(secondHashSet) + "> milliSeconds");
System.out.println("filling linkedSet: <" + fillSet(secondLinkedHashSet) + "> milliSeconds");
System.out.println("filling treeSet: <" + fillSet(secondTreeSet) + "> milliSeconds");
这就是我的填充集的样子:
private static int size = 1000000;
private static int predefinedSize = 2000000;
public static double fillSet(LinkedHashSet<Integer> myHashSet){
double timeStart = System.nanoTime();
for(int i=0; i<size; i++){
myHashSet.add(i);
}
double time = (System.nanoTime() - timeStart)/ Math.pow(10, 6);
return time;
}
输出是这样的:
filling hashSet: <52.14022> milliSeconds
filling linkedSet: <95.599435> milliSeconds
filling treeSet: <2172.773956> milliSeconds
-------------------------------------------------------------
filling hashSet: <59.096929> milliSeconds
filling linkedSet: <1006.638126> milliSeconds
filling treeSet: <241.36395> milliSeconds
你会看到输出差异很大,我认为这取决于我的电脑的计算能力,但我不在后台运行任何其他程序。 有人可以给我解释和/或解决方案吗?
最佳答案
正如 @kan 的评论所提到的,使用系统计时器并执行某件事一百万次将提供截然不同的结果。您正在寻找的是微基准:
How do I write a correct micro-benchmark in Java?
至于你的计时到处都是的原因,你必须阅读有关计算机体系结构和 Java JVM 的知识。一些可能性:
- 处理器中的动态时钟速度技术 https://electronics.stackexchange.com/questions/62353/how-can-a-cpu-dynamically-change-its-clock-frequency - 您可以通过关闭 CPU 更改时钟速度的功能来消除这种可能性。
- 您的集合有 100 万个 Int 类型的元素,大小为 4 MiB。鉴于非服务器 CPU 将具有 1 到 8 MiB 的缓存,该大小几乎达到了是否适合处理器缓存的极限。如果在一次执行中您的 100 万个元素在缓存中停留的时间比另一次执行中的时间长,那么您将获得截然不同的执行时间。您可以通过将集合设置得足够小以适应缓存(最多几十千字节)或太大以使其根本无法与缓存一起使用(也许是一百兆字节),从而消除这种可能性。
- 您可能没有运行任何其他应用程序,但您的计算机上仍有其他内容在后台运行。 (防病毒、更新服务、10-20 项与操作系统内部工作相关的其他任务)
- Java 虚拟机的行为可能有所不同(这一点我不太确定,因为我不是 JIT、GC 和其他可能影响执行时间的东西的内部工作原理的专家)。微基准库将在很大程度上消除这种可能的差异。
关于java - 测量执行时间的常用技术提供不同的值(java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37230673/