用Java测量排序时间

时间:2012-03-15 16:44:58

标签: java sorting benchmarking

我写了一个程序来测试和验证“插入排序”的运行时间,它应该是O(n ^ 2)。输出对我来说看起来不正确,并且在不同的运行之间似乎没有太大变化。另一个奇怪的事情是第二次通过总是最小的。我希望每次运行程序时都会有更大的差异,但运行时间似乎没有像我预期的那样波动。我只是想知道JVM或编译器是否进行了某种优化或某些操作。我在C#中有类似的代码,它似乎变化更多,输出是预期的。我并不期望每次的运行时间都是正确的,但我期望它们比它们增加更多,我当然希望在最后一次迭代时有更大的变化。

示例输出(它不足以让我包含多个输出):

  • 47
  • 20(这个总是最低的......没有意义!)
  • 44
  • 90
  • 133
  • 175
  • 233
  • 298
  • 379
  • 490

    public class SortBench {
    
    public static void main(String args[]){
    
        Random rand = new Random(System.currentTimeMillis());
    
        for(int k = 100; k <= 1000; k += 100)
        {
            //Keep track of time
            long time = 0;
            //Create new arrays each time
            int[] a = new int[k];
            int[] b = new int[k];
            int[] c = new int[k];
            int[] d = new int[k];
            int[] e = new int[k];
    
            //Insert random integers into the arrays
            for (int i = 0; i < a.length; i++)
            {
                int range = Integer.MAX_VALUE;
                a[i] = rand.nextInt(range);
                b[i] = rand.nextInt(range);
                c[i] = rand.nextInt(range);
                d[i] = rand.nextInt(range);
                e[i] = rand.nextInt(range);
            }
            long start = System.nanoTime();
            insertionSort(a);
            long end = System.nanoTime();
            time += end-start;
    
            start = System.nanoTime();
            insertionSort(b);
            end = System.nanoTime();
            time += end-start;
    
            start = System.nanoTime();
            insertionSort(c);
            end = System.nanoTime();
            time += end-start;
    
            start = System.nanoTime();
            insertionSort(d);
            end = System.nanoTime();
            time += end-start;
    
            start = System.nanoTime();
            insertionSort(e);
            end = System.nanoTime();
            time += end-start;
    
            System.out.println((time/5)/1000);
        }
    }
        static void insertionSort(int[] a)
        {
            int key;
            int i;
            for(int j = 1; j < a.length; j++)
            {
                key = a[j];
                i = j - 1;
                while(i>=0 && a[i]>key)
                {
                    a[i + 1] = a[i];
                    i = i - 1;
                }
                a[i + 1] = key;
            }
        }
    }
    

2 个答案:

答案 0 :(得分:3)

在第一次迭代中,您测量JIT时间(或至少某些 JIT时间 - HotSpot将逐步优化)。首先运行几次,然后开始测量。我怀疑随着时间的推移你会看到HotSpot的好处 - 早期的测试因JIT 所花费的时间而减慢,因为它没有作为最佳代码运行。 (与.NET比较,JIT只运行一次 - 没有渐进式优化。)

如果您可以,也可以先分配所有内存 - 并确保在结束前不会收集任何内容。否则,你的时间安排包括分配和GC。

您还应该考虑尝试采用更多样本,n上升另一个数量级,以便更好地了解时间的增加情况。 (我没有仔细研究你所做的事情,以确定它是否真的 应该是O(n 2 )。)

答案 1 :(得分:1)

在随机rand = new Random(System.currentTimeMillis())之后添加以下内容进行预热;

for(int k = 100; k <= 10000; k += 100) 
{
    int[]w = new int[1000];
    for (int i = 0; i < w.length; i++) 
    { 
       int range = Integer.MAX_VALUE; 
       w[i] = rand.nextInt(range); 
       insertionSort(w);
     }
 }

变暖的结果:

4
16
27
47
68
97
126
167
201
250

没有变暖的结果:

62
244
514
206
42
59
80
98
122
148