【问题标题】:Poor performance of Array.map(f: A => B) in ScalaScala 中 Array.map(f: A => B) 的性能不佳
【发布时间】:2012-10-11 13:39:36
【问题描述】:

请有人向我解释一下,为什么 Array.map(f: A=> B) 方法的实现方式比这段代码慢 5 倍以上:

val list = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
val newList = new Array[Int](size)

var j = 0  
while (j < size) {
  newList(j) = list(j)
  j += 1
}

由 TraversableLike trait 提供的 Array 类中的方法 map(f: A=> B) 使用 Scala 'for loop' 来迭代输入 Array 对象的元素,这当然比使用慢得多'while 循环'。

Scala 版本:2.9.2 Java:jdk1.6.0_23 64位窗口

【问题讨论】:

  • 所以你的意思是上面的代码比val newList = list.map(x =&gt; x)快?
  • 我想看看你是如何测量的。您是否使用过像 caliper 这样的微型基准测试框架?
  • map over Array 将构建 ArraySeq,然后将结果复制到新数组中

标签: arrays performance scala map for-loop


【解决方案1】:

map 是一个通用操作(还没有专门化)。因此,您必须在进出功能的过程中对操作进行装箱/拆箱。不出所料,它要慢得多。这是罪魁祸首,而不是使用的循环样式。

这样做的原因是为了代码的一致性和易于维护。由于有无数人无限细心地编写代码,每种方法都是手工制作的,以实现最佳速度,同时仍然是通用的。通用实用程序比速度更受青睐,因为您总是可以通过手动编写 while 循环来恢复速度,但如果它不是通用的并且您需要它,那么您就会陷入困境。

通过对原始集合的操作来提高 Scala 的性能是一个目标,但可能不是 Scala 团队的首要目标。目前,如果您需要速度,请使用 while 循环。

【讨论】:

  • 虽然对数组的操作应该是最先优化的事情,因为性能是使用数组的唯一原因(好吧,或者是大小限制)。
  • @ziggystar - 或 Java 互操作性。
  • 谢谢。说得通。不错的 Collection API,包括 map、filter、reduce 方法,是主要特性之一,它首先吸引了我使用 Scala。但是,自从我开始在贝叶斯网络中研究一些高度计算密集型推理算法以来,我基本上是在重写类似函数的代码以使其更具命令性。
  • @user1763278 - 使用函数式还是命令式风格是一个不同的问题——这也可以提高性能(除了通用操作与原始操作)。但无论哪种方式,重构计算中计算量最大的部分,使其不像惯用的 Scala,而更像是注重性能的 Java,这是我经常做的事情。请记住,您只需要对算法的核心进行这种处理——程序的其余部分可以充分利用漂亮的集合等。
猜你喜欢
  • 1970-01-01
  • 2016-09-16
  • 1970-01-01
  • 1970-01-01
  • 2019-01-27
  • 2015-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多