arrays - 为什么 Array.slice 如此(令人震惊!)慢?

标签 arrays performance scala

这是我的基准代码:

def bm(duration: Long)(f: => Unit)={
  val end = System.currentTimeMillis + duration
  var count = 0
  while(System.currentTimeMillis < end) { f; count += 1 }
  count
}

val array = new scala.util.Random().alphanumeric.take(1000).toArray

(1 to 20).map { _ => bm(1000) { array.slice(100,200) } }.sum / 20

运行多次后,我始终得到大约每秒 150 万个切片的数字。 1.4 到 1.6 之间。

现在,我这样做:

 implicit class FastSlicing(val a: Array[Char]) extends AnyVal {
   def fastSlice(from: Int, until: Int)  = Arrays.copyOfRange(a, from, until)
 }
 (1 to 20).map { _ => bm(1000) { array.fastSlice(100,200) } }.sum / 20

我得到的结果是每秒 16 到 1800 万个切片。 这快了 10 倍以上

现在,我知道了有关 scala 为提供功能惯用语和类型安全而有时以性能为代价进行权衡的所有常见推理...... 但在这种情况下,我认为他们都未能回答一个简单的问题:为什么 ArrayOps.slice 不以这种方式实现???我意识到,由于 java 处理原始数组的方式,需要多个相同的实现,但这最多只是一个小烦恼,并不是真正的破坏性问题来证明 10 倍的性能下降是合理的。

.slice 只是一个示例,大多数其他数组操作似乎也遇到同样的问题。为什么一定要这样?

现在更新,这是我觉得更令人震惊的事情:

val seq = new scala.util.Random().alphanumeric.take(1000).toIndexedSeq
(1 to 20).map { _ => bm(1000) { seq.slice(100,200) } }.sum / 20

这对我来说每秒大约可以处理 5-600 万个切片。但这:

import scala.collections.JavaConversions._
(1 to 20).map { _ => bm(1000) { seq.subList(100,200) } }.sum / 20

数量在 12 到 1500 万之间! 当然,这不是数量级的差异,就像在数组的情况下一样,但是(1)这里没有涉及对原语的特殊处理,因此仅使用 java 标准工具实现这将是完全微不足道的,并且(2)集合是不可变的...返回对一系列索引的引用有多难???

最佳答案

已修复 scala 2.12 .

关于arrays - 为什么 Array.slice 如此(令人震惊!)慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37969193/

相关文章:

arrays - node.js 流数组的 json 响应

postgresql - 有效地修剪 postgresql 表

javascript - 在 Javascript 中快速管理约 10k 行的表

scala - 在 ScalaCheck 中从语法生成字符串

scala - 如何在 Spark 1.5 中转置数据帧(没有可用的枢轴运算符)?

java - 在 Actor 中停止 Akka Actor

javascript - 如何使用 match() 分割数组中的行?

c - 使用大括号将数据分配给数组

c++ - 如何将一个非常大的二进制数转换为十进制数?

performance - 用于高性能、低占用空间的图形查询的库?