【问题标题】:Difference between returning Future.failed(Exception) and throwing an Exception返回 Future.failed(Exception) 和抛出异常之间的区别
【发布时间】:2015-07-02 20:32:53
【问题描述】:

在 Scala 中,返回 Future.failed(new Exception("message!"))throw new Exception("message!") 有什么区别?

假设这发生在一个要返回Future[Unit]的函数中,调用函数是这样的:

someFunction onFailure {
  case ex: Exception => log("Some exception was thrown")
}

是否有一个优先于另一个的偏好或每个特定的用例?

【问题讨论】:

    标签: scala


    【解决方案1】:

    调用Future { throw ex }Future.failed(ex) 将创建等效结果。但是,使用Future.failed 效率更高。如果我们从Future.apply(来自here in the source)看这个sn-p:

    promise complete {
        try Success(body) catch { case NonFatal(e) => Failure(e) }
    }
    

    我们注意到(正如所料),这依赖于 try...catch 块。与普通代码相比,这些已知会带来沉重的开销。 Future.failed 方法本质上是一个捷径,而不必承担实际抛出异常的成本。

    【讨论】:

    • 实际上,异常处理中的大部分开销来自异常的实例化(因为它们——默认情况下——捕获堆栈,这非常昂贵)。因为您要以任何一种方式实例化异常(无论您使用Future.failed 还是Future { throw ex }),该部分都不会进入等式。这只需要考虑实际的投掷/接球机制。这当然是有代价的,但它首先是由创建异常的成本支配的,所以在实践中使用任何一种风格都没有那么重要。
    • 为了给你一个想法,我做了一个(完全不科学的)基准来比较“新异常+抛出+捕获”案例和“新异常”案例的执行时间,区别是在我的机器上不到 1%。
    • 很公平。我想知道内存使用等其他因素是否也存在差异。无论如何,我会说failed 方法更干净、更惯用。
    • 其实让我在这里更正一下。 使用Future { throw ex } 比使用Future.failed(ex) 对性能有很大影响,尽管(正如我所说)它与异常处理本身没什么关系。罪魁祸首实际上是Future.applyExecutionContext 上执行(而Future.failed 直接返回一个完整的Future),因此这会导致显着的额外延迟(Future 将在未来,加上上下文切换的影响)。所以是的,Future.failed(ex) 的性能明显更高。
    猜你喜欢
    • 1970-01-01
    • 2011-03-01
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 2016-07-21
    • 2014-10-23
    • 1970-01-01
    • 2017-09-22
    相关资源
    最近更新 更多