私は最近さまよっていました.ScalaはJVMで実行され、後者はいくつかのタイプの操作に最適化されているため、JVMでの実装が本当に非効率的であり、したがって使用をお勧めできない機能はありますか? また、なぜ非効率なのか説明していただけますか?
最初の候補は関数型プログラミング機能です。私が知っているように、関数はapply
メソッドを持つ特別なクラスであり、関数が単なるコードのブロックである言語と比較して、明らかに追加のオーバーヘッドが発生します。
私は最近さまよっていました.ScalaはJVMで実行され、後者はいくつかのタイプの操作に最適化されているため、JVMでの実装が本当に非効率的であり、したがって使用をお勧めできない機能はありますか? また、なぜ非効率なのか説明していただけますか?
最初の候補は関数型プログラミング機能です。私が知っているように、関数はapply
メソッドを持つ特別なクラスであり、関数が単なるコードのブロックである言語と比較して、明らかに追加のオーバーヘッドが発生します。
パフォーマンス チューニングは深く複雑な問題ですが、すぐに 3 つのことが思い浮かびます。
検討:
(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
最初のものは驚くほどコンパクトです。2 番目は 16 倍高速です。整数の計算は非常に高速です。ボクシングとアンボクシングはありません。ジェネリック コレクション コードは、まあ、ジェネリックであり、ボクシングに依存しています。
プリミティブに対するその他の操作には、ボクシングが必要です。注意してください!
機能を切り替えることができる関数が必要だとします。文字を大文字にするかどうかなどです。試してみて:
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))
2 番目のマップの方が高速ですよね。平行だからですか?
しそうにない!オーバーヘッドのために10倍遅くなります(私のマシンでは、結果は大幅に異なる場合があります)
これらは、コードの最もパフォーマンスが重要な部分を除いて、通常は気にする必要のない非常に多くの問題のほんの一部です。もっとたくさんありますが、最終的にはあなたが遭遇するでしょうが、私のコメントで述べたように、それらのかなりの部分をカバーするには本が必要です. どの言語にもパフォーマンスの問題が山ほどあり、最適化はしばしば難しいことに注意してください。重要なところに労力を節約しましょう。