[英]Scala pattern matching performance
我从coursera“scala specialization”做作业时遇到了这个问题(这是简化版,不包含任何作业细节,只是数组遍历)
val chars: Array[Char] = some array
def fun1(idx:Int):Int = {
some code here (including the stop condition)
val c = chars(idx)
c match{
case '(' => fun1(idx+1)
case _ => fun1(idx+1)
}
}
这段代码慢了4倍
def fun2(idx: Int):Int = {
some code here (including the stop condition)
val c = chars(idx)
(c == '(') match{
case true => fun2(idx+1)
case _ => fun2(idx+1)
}
}
我正在做的就是改变模式匹配(我使用ScalMeter运行它,所以我相信统计数据)。
谁能解释这种行为?
我只能确认第一match
慢了约50%,而不是4x(2.11.8)。 无论如何,如果你查看字节码,你会发现第一个match
被转换为tableswitch
指令,通常用于具有多个选择的Java switch
语句,并且基本上是一个查找goto,而第二个被转换为if
。 所以第二match
很简单:
if (c == '(') fun2(idx+1) else fun2(idx+1)
更新以下是错误的(这些测试中的大部分时间用于生成数据,因此实际遍历时间的差异并不明显。使用常量输入运行相同的基准测试显示每1亿个条目~125ms用于case ')'
案例对于另一种情况,约为35毫秒。)
我没有看到你所描述的差异。 不确定ScalaMeter是如何做到的,但是在repl中运行它(在通过运行“干”几次让“热身”之后),我得到几乎相同的性能:
def func(s: Seq[Char], idx: Int): String =
if(idx == s.length) "foo" else s(idx) match {
case ')' => func(s, idx+1)
case _ => func(s, idx+1)
}
def func1(s: Seq[Char], idx: Int): String =
if(idx == s.length) "foo" else (s(idx) == '(') match {
case true => func(s, idx+1)
case _ => func(s, idx+1)
}
import scala.util.Random
def randy = Stream.continually(Random.nextPrintableChar)
def doit(n: Int)(f: (Seq[Char], Int) => String) = {
val start = System.currentTimeMillis;
f(randy.take(n).toIndexedSeq, 0);
System.currentTimeMillis - start
}
scala> doit(1000000)(func)
res9: Long = 231
scala> doit(1000000)(func1)
res10: Long = 238
scala> doit(1000000)(func)
res11: Long = 234
scala> doit(1000000)(func1)
res12: Long = 201
等等。正如您所看到的,没有相当大的差异。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.