繁体   English   中英

Scala模式匹配性能

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM