【发布时间】:2018-10-18 07:30:58
【问题描述】:
在 Scala 中抛出异常是否昂贵?
更具体地说,当为将来的调用映射异常时,例如:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
val fut: Future[Int] = Future(1)
x和y在性能方面有很大区别吗?
case class MappedException(message: String) extends Exception(message)
val x = fut.recover {
case e => throw MappedException(e.getMessage)
}
val y = fut.recoverWith {
case e => Future.failed(MappedException(e.getMessage))
}
【问题讨论】:
-
我认为在昂贵性方面没有“太大”的差异(如果任何异常处理/堆栈展开开销没有被所有“映射”相形见绌,那会非常惊讶)。第二个在风格上似乎更惯用(你不想
throwScala 中的异常,你想返回失败)。我怀疑两者的最终结果是相同的。 -
只有微基准测试才能提供明确的答案。然而,正如 Josh Bloch 在 Effective Java(第 69 条,第 3 版)中指出的那样,对控制流使用异常(就像您在计算
x时所做的那样)可能会导致性能下降。你计算y的方式——我只是在猜测——比你计算x的方式更有效,而且无论如何,更惯用的Scala 代码。将异常视为值而不是抛出它们。 -
标题具有误导性,您真正要问的是
Future.apply和Future.failed(或Future.successful)之间的区别。第二个效率更高,所以y应该更快。
标签: scala exception-handling throw