并发模型:Erlang vs Clojure

58
我们将使用Clojure编写并发程序,该程序将从大量进入的电子邮件中提取关键字,并将与数据库进行交叉检查。
我的其中一位队友建议使用Erlang来编写此程序。
我想在这里注意一些事情,我对函数式编程还很陌生,因此我有点怀疑是否Clojure是编写此程序的好选择,或者Erlang更合适。

Erlang的字符串处理不是有些次优吗?(为了避免并发讨论...) - kotarak
7
在我看来,如果你使用不当,Erlang 中的字符串处理只会是次优的。例如,使用二进制非常高效。 - Adam Lindberg
Erlang的语法很奇怪:http://damienkatz.net/2008/03/what_sucks_abou.html - Hamish Grubijan
11
对于一个喜欢Lisp的人(我假设是因为这是Erlang vs. Clojure),会用Erlang奇怪的语法来进行争论,这让人感到惊讶。两者都有不熟悉的语法,可以独立存在,但却被许多人所鄙视。优雅之美在于欣赏者的眼中,我不会感到惊讶,如果有几十个程序员认为这两种语言看起来很糟糕的话(事实上我喜欢Lisp和Erlang)。 - I GIVE TERRIBLE ADVICE
5个回答

65
你是真的需要并发还是分布式呢?
如果你需要并发(多线程,多核等),那么我会说Clojure是最合适的解决方案。
- Clojure的STM模型非常适合多核并发,因为它能高效地存储和管理线程之间共享的状态。如果想了解更多,请看这个优秀的视频。 - Clojure的STM允许并发线程安全地修改数据。Erlang通过使所有内容都是不可变的来规避这个问题,本身没什么问题,但当你真正需要共享的可变状态时就无法帮助你。如果你想在Erlang中实现共享可变状态,则必须使用一组消息交互来实现,这既不高效也不方便(这是“nothing shared model”的代价...)。 - 如果在大型机器的并发环境中,使用Clojure可以自然而然地获得更好的性能,因为Clojure不依赖于消息传递,因此线程之间的通信可以更加高效。
如果你需要分布式(即许多不同的机器在网络上共享工作,并且实际上运行为隔离的进程),那么我会说Erlang是更自然的解决方案:
- Erlang的不可变和nothing-shared消息传递风格强制你以可以分布式的方式编写代码。因此,惯用的Erlang自动地可以在多台机器上分布并在分布式、容错的环境中运行。 - 因此,Erlang非常适合这种情况,并且肯定是最快得到可用的选择。 - Clojure也可以完成这个任务,但你需要做更多的工作(即你需要实现或选择某种形式的分布式计算框架)--Clojure目前没有默认提供这样的框架。
从长远来看,我希望Clojure开发出一个与Erlang匹配的分布式计算框架--那么你就可以拥有两全其美的最佳选择!

9
并发和并行不是同一件事。Erlang支持非常自然的并发,处理并行的方法也有效。STM、消息传递、promises和futures都是获得并发和并行的有效选项。你需要哪一个取决于你想要解决的问题的性质。 - I GIVE TERRIBLE ADVICE
2
在Erlang中,ETS表可用于共享可变状态。 - jtmoulia
3
不要忘记 Erlang 的进程级垃圾回收,即使 Clojure "开发了一个分布式计算框架",JVM 的垃圾回收也无法匹配 Erlang 的垃圾回收。 - Erik Kaplun

51

这两种语言和运行时采用了不同的并发处理方法:

  • Erlang将程序结构化为许多轻量级进程彼此之间通信。在这种情况下,您可能会有一个主进程向许多工作进程和更多处理结果数据的进程发送作业和数据。

  • Clojure倾向于使用共同数据结构,使几个线程共享数据和状态。这听起来特别适合许多线程访问相同数据(只读)和共享很少可变状态的情况。

您需要分析应用程序以确定哪种模型最适合您。这也可能取决于您使用的外部工具-例如,数据库处理并发请求的能力。

另一个实际考虑因素是Clojure运行在JVM上,许多开源库都可以使用。


6
好的回答。请注意,即使共享状态是可变的,Clojure并发STM模型同样适用。实际上,协调对共享可变状态的更改是Clojure STM方法的主要动因。 - mikera
1
在我的有限经验中,“许多线程访问相同的数据(只读)并共享很少的可变状态”已经涵盖了我尝试解决的99%问题。 - FUD

10

Clojure 是在 Java JVM 上运行的 Lisp 语言。Erlang 从基础开始就被设计成高度容错和并发。

我认为使用这两种语言及其他许多语言都可以完成任务。你的经验将取决于你对问题的理解程度以及你对语言的熟练程度。如果你对两者都是新手,那么无论你选择哪种语言,问题都会具有挑战性。

您有考虑过类似 Lucene/Solr 这样的软件吗?它是索引和搜索文档的绝佳软件。我不知道“交叉检查”对于您的上下文意味着什么,但这可能是一个值得考虑的好方案。


2
我听说过Clojure的一流并发模型,但是Erlang有更加可靠的声誉。这就是我为什么有疑虑的原因。尽管我有点偏向Clojure,但我不想开始使用它然后后来遇到问题。至于交叉检查,我指的是将那些邮件关键字搜索在词典中,以便分类邮件。 - Quazi Farhan
顺便提一下,Lucene/Solr 对于这个目的也很有趣。谢谢。 - Quazi Farhan
1
你甚至可以在Clojure中使用Lucene/Solr,这是最好的选择。 - Quazi Irfan

0

我的方法是在每种语言中编写一个简单的测试,并测试每种语言的性能。这两种语言与C风格语言有些不同,如果你不习惯它们(并且你没有一个熟悉它们的团队),你可能会遇到维护上的噩梦。

我还会考虑使用类似Groovy 1.8的东西。现在,Groovy包括GPars以实现并行计算。在Groovy中进行字符串和文件操作非常容易。


-4
  • 这要看你所说的“巨大”是什么意思。
  • Erlang中的字符串很痛苦。

但是:

如果“巨大”意味着数十台分布式机器,那么使用Erlang并使用文本友好型语言(如Python?Perl?)编写工作进程。您将在顶部拥有高度并发的本地工作进程的分布式层。每个工作进程都由Erlang进程表示。如果需要更高的性能,请将工作进程重写为C。在Erlang中,与其他语言交互非常容易。

如果“巨大”仍然意味着一台强大的机器,请选择JVM。那就不算太大了。

如果“巨大”是数百台机器,我认为您需要像Google一样的更强大的东西(Bigtable、Map/Reduce),可能在C++堆栈上。Erlang仍然可以,但是您需要优秀的开发人员来编写它。


3
在Erlang中,字符串很痛苦吗?我并不完全同意这一点。可能是因为每次都需要从头开始处理或者因为它缺乏Python字符串处理的尖端技术。在我需要进行的字符串处理方面,我在Erlang和Python 2.x中使用的量是相同的。 - Muzaaya Joshua
我不介意写东西,但处理编码特别麻烦。另外字符串是一个列表,它在堆上分配.. 它不高效地使用内存并且难以分析。 - user425720

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接