Scala Collection对sort,sortWith和sortBy Performance进行了排序

时间:2014-05-11 03:34:17

标签: performance list scala sorting collections

Scala在标准库中包含了几种排序列表的方法,例如对列表 list 进行排序,可以使用:

list.sorted
list.sortWith(_<_)
list.sortBy(x=>x)

虽然这些可能是对列表进行排序的最简单方法,但我发现对于较大的列表,它们具有显着的性能缺陷。

例如,要排序一百万个整数,排序平均需要500毫秒,而sortWith和sortBy需要大约700毫秒。这与scala.util.Sorting.quickSort(需要大约120ms)和java.util.Arrays.sort(需要大约100ms)进行比较。对于较大的列表,随着我们进一步扩展,会观察到这种多因素差异。该模式如下图所示。

Performance of various Scala sorting methods

这种性能滞后的原因是什么?为什么用于标准方法的算法/实现效率更高?

1 个答案:

答案 0 :(得分:19)

注意线条的斜率是多少,但是相互偏移?使用对数标度,我们正在寻找一个恒定的因子差异。 sorted和朋友支付将List转换为Array,排序(实际上使用java.util.Arrays.sort)并转换回List的费用。 scala.util.Sorting.quickSortjava.util.Arrays.sort直接对数组进行操作。快速排序log n性能中的n log n因素在很大程度上是不相关的,因此,使用创建数组所需的线性时间和结果列表,我们最终会得到恒定的因子差异。性能差五倍可能看起来很糟糕,但请记住List每个元素都有一个cons单元格,这会在创建Array时产生大量的随机访问权限,然后创建新的List需要花费时间分配内存,并且很可能需要一两个垃圾收集周期。

对于原语列表,情况更糟。 List是通用的,因此任何基元都必须加框,这会增加另一层间接。不幸的是,创建的Array也包含盒装值。实际上,当您真正想要对Array[java.lang.Integer]进行排序时,最终会对Array[Int]进行排序。

总结一下:排序算法是相同的,但有很多理由说明可变数组的性能优于不可变的单链表。