【问题标题】:How does one clearly structure dependencies between core.async channels?如何清晰地构建 core.async 通道之间的依赖关系?
【发布时间】:2016-02-13 02:31:33
【问题描述】:

假设我有一个计算语料库,我想使用 core.async 异步运行,但不幸的是,其中一些函数依赖于 other 函数的输出。如何在我的代码中清晰地构建它,同时获得最佳性能?

我遇到的一些潜在解决方案是

  • Prismatic's Graph - 看起来很合理,虽然我没有用 core.async 通道测试过它;它需要使用 fnk 的事实对我来说有点令人反感,因为它需要购买他们的 DSL 来进行函数定义,但如果这是最好的解决方案,那么我不介意。
  • Javelin cells - 仅适用于 ClojureScript(目前)并使用 FRP 而不是 CSP 作为实现,但它在通过公式单元格对计算之间的依赖关系建模方面做得非常好。
  • Onyx - 用于分布式计算(作为 Apache Storm 的竞争对手等),但具有处理计算之间的依赖关系并与 core.async 一起使用的“工作流”抽象。这似乎最适合我的问题域,但我不确定是否需要所有集群管理功能的开销。

这个问题的典型解决方案是什么?

编辑:添加 Onyx

【问题讨论】:

标签: clojure core.async


【解决方案1】:

这个问题有点难以回答,因为您的问题缺乏关于您的用例的细节。 Graph、Javelin 和 Onyx 等库都有不同的用例,不仅仅是让计算相互依赖。

如果您只想让线程或 go 块依赖于系统另一部分生成的结果,我建议您只使用 core.async 原语而不使用任何其他库。

让执行等待另一个活动线程的最基本解决方案是在从通道获取值时使用阻塞接收。当该通道上没有可用值时,这将停止线程(或阻塞)。

正如您在以下示例中所见,使计算依赖于另一个线程中完成的活动非常容易。

(let [c (chan)]
  (thread (>!! c “hello”))
  (assert (= “hello” (<!! c)))
  (close! c)

还有更精细的机制可用。 Alts!! 函数提供了同时在多个通道上等待的能力。 pipeline 函数的几种不同风格允许您以类似数据流的方式对并发进行建模。

您是否遇到过使用内置函数无法清晰表达的具体问题?

【讨论】:

  • 也许是这个? (let [c (chan)] (go (>!! c "hello")) (assert (= "hello" (
【解决方案2】:

我不认为有一个规范的方法可以解决它,core.async 太新了,很少有人尝试过。如果我要在您的三个选项之间进行选择,我会选择 Graph,它已经在生产环境中部署和测试了一段时间,并且您不需要 Clojurescript 来运行它。如果您对 FRP 解决方案感兴趣,请查看 Java Reactive Extensions,它的 Clojure 绑定存在于 RxClojure 中。

【讨论】:

    【解决方案3】:

    对于上面的 #3,onyx-local-rt 可能符合要求:

    onyx-local-rt 是 Onyx 的替代运行时,它在 一个纯粹的、确定性的环境。此运行时仅限本地,并且 不以分布式模式运行。这是一个孵化存储库, 这意味着此代码将在以后移动到 Onyx 核心中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-25
      • 2015-07-04
      • 1970-01-01
      • 2019-04-26
      • 2011-04-30
      • 1970-01-01
      • 1970-01-01
      • 2021-03-12
      相关资源
      最近更新 更多