测量执行时间的常用技术提供不同的值(java)

时间:2016-05-14 18:56:52

标签: java time set execution

我试图在不同类型的集合上测量不同操作的时间并想要比较它们,但是我得到的值在相同类型的集合上非常不同,如因子1000.我使用常用​​技术I在这里阅读: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

你看到输出差别很大,我认为它取决于我的电脑的计算能力,但我不在后台运行任何其他程序。 有人可以给我一个解释和/或解决吗?

1 个答案:

答案 0 :(得分:1)

正如@ 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和其他可能影响其他内容的内部工作没有专家意见执行时间处理时间)。微基准库将在很大程度上消除这种可能的差异。