【问题标题】:Why sorting Long array is slower than sorting long array using Arrays.sort()? [duplicate]为什么排序长数组比使用 Arrays.sort() 排序长数组慢? [复制]
【发布时间】:2013-12-28 04:57:37
【问题描述】:

我得到的结果是,使用Arrays.sort()Long array 进行排序比使用Arrays.sort()long array 进行排序花费更多时间。这是代码。

public class ABtest {

public static void main(String[] args) {
    long startTime;
    long endTime;

    //code block 1
    startTime = System.nanoTime();
    Long a[] = new Long[10000];
    for (int i = 0; i < a.length; i++) {
        a[i] = 12l;
    }
    Arrays.sort(a);
    endTime = System.nanoTime();
    System.out.println("code block (has Long array) 1 = " + (endTime - startTime));



    //code block 2
    startTime = System.nanoTime();
    long c[] = new long[10000];
    for (int i = 0; i < c.length; i++) {
        c[i] = 12l;
    }
    Arrays.sort(c);
    endTime = System.nanoTime();
    System.out.println("code block (has long array) 2 = " + (endTime - startTime));

}
}

运行时间:

code block (has Long array) 1 = 3076331

code block (has long array) 2 = 741501

谁能解释这种行为。还是我在这里做错了什么??

【问题讨论】:

  • 您在进行基准标记时需要非常小心。有很多假设情况发生。 ibm.com/developerworks/java/library/j-benchmark1/index.html
  • Long 必须拆箱才能排序; long 可以按原样排序。加上通常的危害重新基准测试。 (特别是您包括加载数组的时间,在 Long 情况下,这需要对每个值和所暗示的对象创建进行装箱。)
  • 这个问题似乎离题了,因为它是关于基准测试的,并不是一个实际的问题,只是一篇关于他们如何错误地对某些东西进行微基准测试的博文。
  • 实际上,您的“基准”测量的是创建 10K Long 对象所需的时间。

标签: java arrays performance sorting


【解决方案1】:

答案与your other benchmarking Question 的答案相同。您的基准测试设计不当,您看到的计时数字无效/没有意义。


但是,无论如何,对Long[] 进行排序将比对等价的long[] 进行排序要慢:

  • 这部分是因为比较一对Long 值比比较一对long 值需要更长的时间。

  • 此外,如果您查看the source code,您将看到用于排序long[]Object[] 的算法不同。前者使用 Quicksort 的一种形式,后者使用 MergeSort 或 TimSort 的一种形式。

我的理解是算法不同,因为sort算法必须是稳定的;即,如果一对元素相等,则必须保留元素的原始顺序。对于原始类型,您可以忽略它,但对于引用类型(例如Long),这会限制可以使用的排序算法。

(根据@S.Yavari 发布的结果,我怀疑算法的差异是更重要的问题。)

【讨论】:

    【解决方案2】:

    long 值可以进行比较,而装箱的值 Long 需要在比较之前提取(只是预感)。

    您的测试存在问题。您包括分配数组并填充它的时间。您没有给 JVM 太多时间来计算调优的热点,而且您可能还会遇到垃圾收集时间。

    您还可以使用更好的测试数据。已经按升序或降序排序的数组的时序是否存在差异?当数组更随机时它们如何公平?

    【讨论】:

      【解决方案3】:

      这是你的代码在我的机器上的结果:

      第一次运行:

      code block (has Long array) 1 = 6070325
      code block (has long array) 2 = 8739868
      

      第二次运行:

      code block (has Long array) 1 = 4449868
      code block (has long array) 2 = 6224883
      

      第三次运行:

      code block (has Long array) 1 = 5773081
      code block (has long array) 2 = 1160343
      

      我认为您的基准测试设计得很糟糕。 如果我们把代码改成这样:

      import java.util.Arrays;
      
      public class Test {
          public static void main(String[] args) {
              for (int i = 0; i < 10; i++) {
                  System.out.println("Benchmark " + (i + 1));
                  benchmark();
                  System.out.println();
              }
          }
      
          public static void benchmark() {
              long startTime;
              long endTime;
      
              Long a[] = new Long[10000];
              long b[] = new long[10000];
      
              for (int i = 0; i < a.length; i++)
                  a[i] = 12l;
      
              for (int i = 0; i < b.length; i++)
                  b[i] = 12l;
      
              //code block 1
              startTime = System.nanoTime();
              Arrays.sort(a);
              endTime = System.nanoTime();
              System.out.println("\tcode block (has Long array) 1 = " + (endTime - startTime));
      
              //code block 2
              startTime = System.nanoTime();
              Arrays.sort(b);
              endTime = System.nanoTime();
              System.out.println("\tcode block (has long array) 2 = " + (endTime - startTime));
          }
      }
      

      我们可以看到你说的结果。这是因为long 数据类型和Long 对象的比较方法不同。你知道long 是一个原始数据类型,但Long 是一个对象。所以,比较两个long值,系统可以不使用任何复杂的比较方法来比较它们,但是对于比较两个Long对象,JVM应该使用Long对象的比较方法,该方法比较耗时。

      请注意,这是第二个代码的结果:

      Benchmark 1
      code block (has Long array) 1 = 2957778
      code block (has long array) 2 = 751911
      
      Benchmark 2
      code block (has Long array) 1 = 2081759
      code block (has long array) 2 = 392857
      
      Benchmark 3
      code block (has Long array) 1 = 2031473
      code block (has long array) 2 = 410946
      
      Benchmark 4
      code block (has Long array) 1 = 2016387
      code block (has long array) 2 = 360241
      
      Benchmark 5
      code block (has Long array) 1 = 2070235
      code block (has long array) 2 = 360870
      
      Benchmark 6
      code block (has Long array) 1 = 2105156
      code block (has long array) 2 = 360801
      
      Benchmark 7
      code block (has Long array) 1 = 2020928
      code block (has long array) 2 = 386013
      
      Benchmark 8
      code block (has Long array) 1 = 1976229
      code block (has long array) 2 = 359682
      
      Benchmark 9
      code block (has Long array) 1 = 5213093
      code block (has long array) 2 = 363664
      
      Benchmark 10
      code block (has Long array) 1 = 3999880
      code block (has long array) 2 = 361638
      

      【讨论】:

      • 干得好。这些数字是可信的。
      猜你喜欢
      • 2016-09-08
      • 2012-12-11
      • 2016-05-03
      相关资源
      最近更新 更多