performance - 哪些 Scala 特性性能较差

标签 performance scala jvm

我最近在徘徊:由于 Scala 在 JVM 上运行,而后者针对某些类型的操作进行了优化,是否存在在 JVM 上实现效率非常低的功能,因此应该不鼓励使用哪些功能?你能解释一下为什么他们效率低下吗?

第一个候选者是函数式编程特性——据我所知,函数是特殊类,apply方法,与函数只是代码块的语言相比,这显然会产生额外的开销。

最佳答案

性能调优是一个深刻而复杂的问题,但我立即想到了三件事。
Scala 集合有利于表达能力,但不利于性能。
考虑:

(1 to 20).map(x => x*x).sum

val a = new Array[Int](20)
var i = 0
while (i < 20) { a(i) = i+1; i += 1 }  // (1 to 20)
i = 0
while (i < 20) { a(i) = a(i)*a(i); i += 1 }   // map(x => x*x)
var s = 0
i = 0
while (i < 20) { s += a(i); i += 1 }  // sum
s
第一个是惊人的更紧凑。第二个速度快 16 倍。整数数学真的很快;装箱和拆箱不是。通用集合代码是通用的,并且依赖于装箱。
Function2 仅专门用于 Int、Long 和 Double 参数。
对原语的任何其他操作都需要装箱。谨防!
假设您想要一个可以切换功能的功能——也许您想要大写字母或不想要大写字母。你试试:
def doOdd(a: Array[Char], f: (Char, Boolean) => Char) = {
  var i = 0
  while (i<a.length) { a(i) = f(a(i), (i&1)==1); i += 1 }
  a
}
然后你
val text = "The quick brown fox jumps over the lazy dog".toArray
val f = (c: Char, b: Boolean) => if (b) c.toUpper else c.toLower

scala> println( doOdd(text, f).mkString )
tHe qUiCk bRoWn fOx jUmPs oVeR ThE LaZy dOg
好,太棒了!除非我们
trait Func_CB_C { def apply(c: Char, b: Boolean): Char }
val g = new Func_CB_C {
  def apply(c: Char, b: Boolean) = if (b) c.toUpper else c.toLower
}
def doOdd2(a: Array[Char], f: Func_CB_C) = {
  var i = 0
  while (i<a.length) { a(i) = f(a(i), (i&1)==1); i += 1 }
  a
}
反而?突然,它快了 3 倍。但如果是 (Int, Int) => Int , (或任何其他 Int/Long/Double 参数和 Unit/Boolean/Int/Long/Float/Double 返回值的排列),不需要滚动您自己的 - 它是专门的并且以最大速度工作。
仅仅因为您可以轻松并行化并不意味着这是一个好主意。
Scala 的并行集合只会尝试并行运行您的代码。确保有足够的工作以使并行运行是明智之举,这取决于您。设置线程和收集结果有很多开销。举个例子,
val v = (1 to 1000).to[Vector]
v.map(x => x*(x+1))
相对
val u = (1 to 1000).to[Vector].par
u.map(x => x*(x+1))
第二张 map 更快,对吧,因为它是平行的?
几乎不!由于开销,它慢了 10 倍(在我的机器上;结果可能会有很大差异)
概括
这些只是您通常不必担心的许多问题中的一小部分,除了代码中对性能最关键的部分。还有更多,最终你会遇到,但正如我在评论中提到的,需要一本书才能涵盖其中的相当一部分。请注意,任何语言都存在大量性能问题,优化通常很棘手。把你的精力放在重要的地方!

关于performance - 哪些 Scala 特性性能较差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16210095/

相关文章:

c# - 调用 Web 服务时最有效的 C# Tasks 和 Continuations 配置?

scala - 使用密封案例对象的枚举类型(从 haskell 到 scala)

scala - Spark 读取 Avro 文件

java - 我的 jar 可以在 Ubuntu 上运行,但不能在 Windows 上运行

memory-management - JVM 和 CLR 分配优化

json - Postgres - 大型 jsonb 列的性能

javascript - 网站加载时间的脚本

iOS - 性能测试?

scala - 如何使用 Scala 2.8 将 String* scala vararg 传递给 java 方法

java - JVM 中的 JIT 编译器到底是什么?