为什么阻止未来被认为是一种不好的做法?

2023-12-30

我试图理解该声明背后的理性对于绝对需要封锁的情况,期货可以被封锁(尽管不鼓励这样做) http://docs.scala-lang.org/sips/pending/futures-promises.html

背后的想法ForkJoinPool是加入阻塞操作的进程,这是 future 和 actor 的执行器上下文的主要实现。它对于阻止连接应该是有效的。

我写了一个小基准测试,看起来旧式 futures(scala 2.9)在这个非常简单的场景中速度快了 2 倍。

@inline
  def futureResult[T](future: Future[T]) = Await.result(future, Duration.Inf)

  @inline
  def futureOld[T](body: => T)(implicit  ctx:ExecutionContext): () => T = {
    val f = future(body)
    () => futureResult(f)
  }

  def main(args: Array[String]) {
    @volatile

    var res = 0d
    CommonUtil.timer("res1") {
      (0 until 100000).foreach {  i =>
       val f1 = futureOld(math.exp(1))
        val f2 = futureOld(math.exp(2))
        val f3 = futureOld(math.exp(3))
        res = res + f1() + f2() + f3()
      }
    }
    println("res1 = "+res)
    res = 0

    res = 0
    CommonUtil.timer("res1") {
      (0 until 100000).foreach {  i =>
        val f1 = future(math.exp(1))
        val f2 = future(math.exp(2))
        val f3 = future(math.exp(3))
        val f4 = for(r1 <- f1; r2 <- f2 ; r3 <- f3) yield r1+r2+r3
        res = res + futureResult(f4)
      }
    }
    println("res2 = "+res)
  }



start:res1
res1 - 1.683 seconds
res1 = 3019287.4850644027
start:res1
res1 - 3.179 seconds
res2 = 3019287.485058338

大部分的pointFutures 的特点是它们使您能够创建可以轻松并行执行的非阻塞并发代码。

好的,所以将一个可能很长的函数立即包装在 future 返回中,这样您就可以推迟担心返回值,直到您真正对它感兴趣为止。但是如果代码的一部分does关心的值只是阻塞,直到结果实际可用,你所获得的只是一种使你的代码更整洁的方法(你知道,你可以在没有 future 的情况下做到这一点 - 使用 future 来整理你的代码将是一种代码味道, 我认为)。除非封装在 future 中的函数绝对微不足道,否则您的代码将花费比评估其他表达式更多的时间进行阻塞。

另一方面,如果您注册回调(例如使用完成时 or 成功时)并在该回调中放入关心结果的代码,然后您就可以拥有可以组织起来非常有效地运行并良好扩展的代码。它变成事件驱动的,而不是必须坐下来等待结果。

您的基准测试属于前一种类型,但由于其中有一些微小的函数,因此与顺序执行相比,并行执行它们几乎没有什么好处。这意味着您主要评估创建和访问 future 的开销。恭喜:您表明,在某些情况下,2.9 future 在做一些琐碎的事情时比 2.10 更快 - 一些琐碎的事情并没有真正发挥出该概念的任何一个版本的优势。

尝试一些更复杂和要求更高的东西。我的意思是,你要求的是未来的价值几乎立即!至少,您可以构建一个包含 100000 个 future 的数组,然后在另一个循环中取出它们的结果。那将是测试某物稍微有点意思。哦,让他们根据以下值计算一些东西i.

你可以从那里进步到

  1. 创建一个对象来存储结果。
  2. 向每个将结果插入对象的 future 注册一个回调。
  3. 启动您的n计算

然后,当您要求所有结果时,对实际结果到达需要多长时间进行基准测试。这样的话就更有意义了。

EDIT

顺便说一句,您的基准测试本身以及对期货正确使用的理解都失败了。

首先,您正在计算检索每个单独的未来结果所需的时间,而不是评估所需的实际时间res创建所有 3 个 future 后,也不是迭代循环所需的总时间。另外,你的数学计算是如此微不足道,以至于你实际上可能在第二个测试中测试惩罚:a) for 理解和 b) 包含前三个 future 的第四个 future。

其次,这些总和可能与所用的总时间大致成正比的唯一原因是because这里确实没有并发。

我并不是想打击你,只是基准测试中的这些缺陷有助于阐明问题。不同期货实现的性能的适当基准需要非常仔细的考虑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么阻止未来被认为是一种不好的做法? 的相关文章

随机推荐