【问题标题】:Haskell, Scala, Clojure, what to choose for high performance pattern matching and concurrency [closed]Haskell,Scala,Clojure,高性能模式匹配和并发的选择[关闭]
【发布时间】:2012-07-23 05:42:53
【问题描述】:

在阅读了很多关于 FP 在并发执行和性能方面的优势的博客和帖子后,我最近开始研究 FP。我对 FP 的需求很大程度上受到我正在开发的应用程序的影响,我的应用程序是一个基于状态的数据注入器,它可以插入另一个时间非常关键的子系统(接近每秒 200 万个事务)。我有几个这样的子系统需要测试。 我正在认真考虑使用 FP 的并行性并希望采用正确的方法,SO 上的许多帖子都谈到了 Scala、Haskell 和 Clojure wrt 语言结构、库和 JVM 支持的优缺点。从语言的角度来看,我可以学习任何语言,只要它能帮助我取得成果。

某些帖子偏爱 Haskell 的模式匹配和语言简单性,基于 JVM 的 FP 语言在使用现有 java 库方面具有很大优势。 JaneStreet 是 OCAML 的忠实支持者,但我真的不确定 OCAML 的开发者支持和帮助论坛。

如果有人处理过如此大的数据,请分享您的经验。

【问题讨论】:

标签: scala haskell clojure programming-languages ocaml


【解决方案1】:

你想要快速还是简单

如果你想要快速,你应该使用 C++,即使你使用 FP 原则来帮助正确。由于时间至关重要,因此对软(和硬,如果需要)实时编程的支持将很重要。您可以准确地决定如何以及何时有时间恢复记忆,并且只在该任务上花费尽可能多的时间。

您所说的三种语言都是~2-3x slower than near-optimally hand-tuned C++ tends to be,然后仅在以相当传统的命令方式使用时。它们都使用垃圾回收,这将在您的事务中引入不受控制的随机延迟。

现在,也就是说,使用 C++ 以防弹的方式运行它是一项大量的工作。应用 FP 原则需要相当多的样板文件(即使在 C++11 中),并且大多数库默认情况下是可变的。 (编辑:Rust 正在成为一个不错的选择,但足够详细地描述 Rust 超出了这个答案的范围。)

也许您没有时间并且有能力缩减其他规格。例如,如果不是 时间 而是 吞吐量 至关重要,那么您可能想要 Scala 而不是 Clojure(参见 Computer Languages Benchmark Game,其中在撰写本文时,Scala 赢得了所有基准测试并且几乎在所有情况下都具有较小的代码大小(编辑:CLBG 在这方面不再有帮助,尽管您可能会在 Web 档案中找到支持这些陈述的档案) );应该选择 OCaml 和 Haskell 有其他原因(类似的基准分数,但它们具有不同的语法和互操作性等)。

就哪个系统的并发支持最好而言,Haskell、Clojure 和 Scala 都还不错,而 OCaml 则有点欠缺。

这几乎将范围缩小到 Haskell 和 Scala。您需要使用 Java 库吗?斯卡拉。您需要使用 C 库吗?可能是哈斯克尔。你都不需要吗?然后,您可以根据自己喜欢的风格进行选择,而不必过分担心选择错误的风格会让您的生活变得更加艰难。

【讨论】:

  • 能否请您添加对“比 C++ 慢 2-3 倍”的引用?谢谢
  • @Ankur - 在以函数式编程时,与 C++ 相比,C 没有增加额外的速度,而是增加了巨大的额外语法负担。选择它的唯一原因是如果使用的平台没有 C++ 编译器(一些嵌入式平台、一些 FPGA 代码生成器等)。我严重怀疑这里的情况。
  • @Edmondo1984 - 我想你误解了我的意思。我认为 Google 文档一点也不好,我不希望包含链接,因为我认为它具有误导性,或者会浪费人们的时间,因为他们仔细阅读并最终意识到它不是很好。 (我不认为他们打算让它很棒——只是有点有趣,然后人们想要阅读的内容比作者的意思要多。)
  • 如今,Rust 可能是一个不错的选择。它具有类似于 Haskell 的模式匹配,并且对 FP 的支持比 C++ 更好,但在基准测试中的性能与 C++ 差不多。
  • @saolof - 同意。如今,Rust 是一个值得探索的替代方案。
【解决方案2】:

我使用 Clojure 完成了这项工作,事实证明它非常有效,原因如下:

  • 就库而言,在 JVM 上是一个巨大的优势。出于我的目的,这有效地排除了 Haskell 和 Ocaml,因为我们需要轻松访问 Java 生态系统并与基于 JVM 的工具(Maven 构建等)集成。
  • 如果您需要严格优化内部循环,您可以使用纯 Java。我们为一些处理大型 double[] 数组的自定义代码执行此操作,但 99% 的时间 Clojure 可以为您提供所需的性能。请参阅http://www.infoq.com/presentations/Why-Prismatic-Goes-Faster-With-Clojure,了解如何让 Clojure 运行得非常快的一些示例(相当技术性的视频,假设有一些先验知识!)。一旦您开始计算利用多核的难易程度,Clojure 在性能上就会非常具有竞争力。
  • Clojure 具有非常好的多核并发支持。事实证明,这对于管理并发任务非常有用。见http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey
  • REPL 为数据测试和探索性工作提供了一个非常好的环境。
  • Clojure 是 lazy 的,这使得它适合处理大于内存的数据集(假设您注意不要尝试将整个数据集一次强制放入内存)。在这样的环境中也有一些不错的库可用,最值得注意的是StormAleph。 Storm 可能对您来说特别有趣,因为它是为大量事件的分布式实时处理而设计的。

我不能说太多其他语言的经验,但我对 Haskell 和 Scala 的一些实践经验的印象是:

  • 如果您关心纯度和使用静态类型的严格函数式编程,Haskell 非常棒。静态类型可以是正确性的有力保证,因此可能使其适用于高度算法的工作。就个人而言,我发现纯 FP 有点过于僵化 - 很多时候可变状态很有用,我认为 Clojure 在这里有更好的平衡(通过通过托管引用允许受控的可变性)。
  • Scala 是一门出色的语言,它与 Clojure 共享在 JVM 上的优势。对我来说,Scala 更像是一个“更好的 Java”,具有功能特性和令人印象深刻的类型系统。这不是从 Clojure 的范式转变。缺点是类型系统会变得相当复杂/令人困惑。

总体而言,我认为您会对其中任何一个感到满意。这可能会归结为您对 JVM 的关心程度以及您对类型系统的看法。

【讨论】:

  • 5 个参数中的 4 个也适用于 Scala(除了最后一个 - Clojure 是惰性的)
  • 是的,同意,我真的很喜欢 Scala,只是没怎么用过。两者都是很棒的语言。可以说,您当然也可以在 Scala 中通过一些努力来产生惰性行为,只是它不像 Clojure 那样“内置”。
  • 很多人(大多数)会认为 Scala 的类型系统是一个优点而不是缺点。
  • 虽然 Clojure 使处理惰性序列变得容易,但称语言惰性通常是指其评估策略。 Haskell is far more lazy than Clojure in this respect,但这可能与这个特定问题无关。
  • 我同意@GordonGustafson。 Clojure 是严格的。我认为您的意思是说它具有用于惰性的内置类型,例如惰性序列/缺点和延迟。为了让它变得懒惰,它必须是非严格的+共享(尽管仍然被赞成)。
猜你喜欢
  • 2016-05-16
  • 2011-04-02
  • 2023-03-12
  • 2011-02-06
  • 2015-06-12
  • 1970-01-01
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多