在性能方面,Scala匹配表达式中的替代顺序是否重要? [英] Does the order of alternatives in a Scala match expression matter in terms of performance?

查看:39
本文介绍了在性能方面,Scala匹配表达式中的替代顺序是否重要?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尤其是在模式匹配和大小写类别方面.请考虑以下内容:

In particular with respect to pattern matching and case classes. Consider the following:

abstract class Expr
case class Var(name: String) extends Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr

object Expr {
  def simplify(expr: Expr): Expr = expr match {
    // Some basic simplification rules...
    case UnOp("-", UnOp("-", e)) => simplify(e) // Double negation
    case BinOp("+", e, Number(0)) => simplify(e) // Adding zero
    case BinOp("-", e, Number(0)) => simplify(e) // Subtracting zero
    case BinOp("*", e, Number(1)) => simplify(e) // Multiplying by one
    case BinOp("*", e, Number(0)) => Number(0) // Multiplying by zero
    case _ => expr // Default, could not simplify given above rules
  }
}

给出任何示例调用,例如 simplify(UnOp(-",UnOp(-",UnOp(-",UnOp(-",Var("x"))))))))(这会导致 Var("x")),匹配表达式中替代项的顺序对性能有影响吗?

Given any sample call, say, simplify(UnOp("-", UnOp("-", UnOp("-", UnOp("-", Var("x")))))) (which results in Var("x")), does the order of the alternatives in the match expression matter for performance?

旁注,一种相关的(我自己的观察):关于 simplify ,真正令我着迷的是它是一个递归函数,尽管与其他递归函数不同我已经写过/处理过了,为了避免提早终止,基本情况是倒数第二个.

Side note, kind of related (my own observation): One thing that really strikes me about simplify is that it is a recursive function, although unlike other recursive functions I've written / dealt with, the base case comes last in order to avoid terminating early.

推荐答案

理论上可以,因为匹配的测试是按顺序进行的.

Theoretically yes, because matching tests are done in order.

但是在实践中,差异可能并不明显.我已经使用Caliper和您的示例运行了微基准测试.我在 Var("x")前面加上了100'000 Unop s,以使其更大.

But in practice the difference can be unsignificant. I've run a micro-benchmark using Caliper and your example. I prefixed Var("x") with 100'000 Unops to make it bigger.

结果是:

[info]  0% Scenario{vm=java, trial=0, benchmark=ForFirst} 240395.82 ns; σ=998.55 ns @ 3 trials
[info] 50% Scenario{vm=java, trial=0, benchmark=ForLast} 251303.52 ns; σ=2342.60 ns @ 5 trials
[info] 
[info] benchmark  us linear runtime
[info]  ForFirst 240 ============================
[info]   ForLast 251 ==============================

在第一个测试中, UnOp 案例是第一个案例,在第二个测试中,它是最后一个案例(就在默认案例之前).

In first test, UnOp case is the first one, in second test its the last one (just before the default case).

如您所见,这并不重要(慢5%以下).也许那是一个大问题,顺序很重要,但它也可能是重构的候选.

As you can see, it does not really matter (less than 5% slower). Perhaps that, with a huge list of case the order matters, but it would also be a candidate for refactoring.

完整代码在这里: https://gist.github.com/1152232 (通过<一个href ="https://github.com/sirthias/scala-benchmarking-template" rel ="noreferrer"> scala-benchmarking-template ).

Full code is here: https://gist.github.com/1152232 (runs via scala-benchmarking-template).

这篇关于在性能方面,Scala匹配表达式中的替代顺序是否重要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆