最近我在思考:由于Scala是运行在JVM上的,而JVM优化了某些类型的操作,因此是否有一些特性的实现在JVM上确实非常低效,使用这些特性应该被阻止?你能否解释一下它们为什么不高效?
第一个可能的候选者就是函数式编程的特性 - 据我所知,函数是具有“apply”方法的特殊类,这显然会产生额外的开销,相比于那些函数只是代码块的语言来说。
第一个可能的候选者就是函数式编程的特性 - 据我所知,函数是具有“apply”方法的特殊类,这显然会产生额外的开销,相比于那些函数只是代码块的语言来说。
性能调优是一个深奥而复杂的问题,但有三件事情需要立即注意。
考虑以下内容:
(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
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
}
需要进行翻译的内容如下:
如果你有一个函数,它带有两个参数并返回一个整数,那么你可能想自己编写一个双重循环,而不是使用 map
和 flatten
。这样做可以让你以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))