性能和Java互操作性:Clojure vs. Scala

83

我已经阅读了有关Clojure vs. Scala的各种说明,尽管我意识到两者都有其适用场景。当比较Clojure和Scala时,有一些考虑因素我还没有完全明白:

1.) 这两种语言中哪一个通常更?我知道这会因语言特性而异,但总体性能的一般评估会很有帮助。例如:我知道Python字典非常快。 但总体而言,它比Java慢得多。 我不想选择Clojure然后在以后遇到这个问题。

2.) 与Java的互操作性如何? 到目前为止,我所看到的所有内容都是Scala具有本地集合类型,这使其与大型Java代码库集成有点笨拙,而Clojure遵循一种简单的Iterable/Iterator为中心的方法来实现与Java类的互操作。对此还有什么更多的想法/细节吗?

最终,如果Clojure和Scala之间的差距足够小,我可能会尝试两者。 Clojure的一件事情是该语言似乎非常简单。 但另一方面,Scala具有非常灵活的类型系统。 但是,我知道Scala很快(基于多个个人账户)。因此,如果Clojure显着较慢:我希望尽早了解。


1
使用Clojure 1.2,Clojure可以在没有开销的情况下调用Java。请查看http://www.assembla.com/wiki/show/clojure/Datatypes和http://www.assembla.com/wiki/show/clojure/New_new。这是因为Clojure希望接近Java,但是实现方式是Clojure。 - nickik
8个回答

73
我认为这两种语言对你来说都足够快。比较Python和Java时,将速度差归咎于语言似乎有点不合理。Java是即时编译的(除了在移动设备上*),而Python是解释的。仅因为两者使用字节码并不意味着实现性能会有相同的表现。但是Scala和Clojure都是JVM语言,所以它们应该具有类似的性能。

Scala在实现方面优于Clojure,我期望它的性能略高一些。尽管Scala的静态类型通常会转化为比Clojure的鸭子类型更快的速度优势,但是Clojure 支持类型提示,可以显著加快代码运行速度。可能,普通的Scala比普通的Clojure更快,但只需要优化瓶颈部分。程序运行时间的大多数是由实际代码中很少量的部分生成的。

关于与Java的互操作性,Scala更接近Java,但我确定两种语言都可以良好地进行交互。在Programming Clojure中,Stuart Halloway写道:“[您可以访问] 从Java代码中可以访问的所有内容。”。

而且,由于Scala作者Martin Odersky 编写了Sun的Java编译器,我认为Scala方面也没有掉链子。 :-)

虽然很难选择两种更好的语言,但我也喜欢Ruby。为什么要担心要尝试哪一种?为什么不都尝试一下呢?Scala更有可能成为“下一个Java”,而很难想象Lisp在50多年后终于会流行起来。但是很明显Lisp处于自己独特的抽象层次,Clojure相当简单,因此Scala + Clojure不会比仅使用Scala(而且相当复杂)更难,我相信你试了之后会感到高兴。

而且,它们可以进行互操作...

* dalvik(Android的JVM)在2010年的2.2版本中获得了JIT编译器


6
好的,谢谢您提供这些见解。起初我想只选择一个并使用它,但出于某种原因,我没有想到可以同时使用两个并让它们互相配合。也许我会选择两个一起用,并且快速地尝试它们。 - Ryan Delucchi
7
我想补充一下,我对LISP有点偏爱,所以Clojure受到括号过多的影响并不足以让我却步。 - Ryan Delucchi
8
并非所有在JVM上编写的编程语言都能以最高速度运行。原始版本的JRuby性能十分糟糕,因为它是一种解释器,是通过JVM编译的,而不是源代码。此外,编程语言本身也可能是罪魁祸首。与动态语言相比,静态类型的语言通常更容易优化等。 - Bill K
8
“Scala和Clojure都是JVM语言,因此它们应该具有类似的性能”这种说法完全没有意义。需要与Java等静态语言保持互操作性的动态语言总是比较慢(重载会带来巨大代价,类型提示并不能解决所有问题等)。 - julx
4
@julkiewicz - 动态语言并不总是慢得多,这种说法并不正确。这取决于编译器是否能够对相关代码进行有效的优化。例如,在Clojure中,你可以使用Java原语进行算术计算,其性能与Java完全相同。同样,对于类型提示的Java对象调用方法与Java对象方法调用一样快。Clojure编译器基本上会为等效的Java代码产生与javac相同的字节码。 - mikera
显示剩余2条评论

32

由于JVM对动态类型的支持——反射技术速度比较慢,因此在目前的JVM中,Scala有一个优势,即它是静态类型的。事实上,Scala的一种特性——结构类型,必须通过相同的技术来实现,但因为这个原因通常会被警告不要使用。

此外,Scala可以很好地接受可变对象,某些算法用可变性实现会更快。

由于Scala和Java本质上都是基于类的语言,它们之间的互操作性更加容易。或者说,更加无缝。Java类对于Scala来说是一个类,而Scala类对于Java来说也是一个类。当涉及到Scala的单例或Java的静态成员时,可能会出现问题,特别是当涉及到期望以某种方式工作的框架时。

因此,在这两个方面我会选择Scala。Clojure在许多方面都是一种更好的语言,并且它肯定具有非常有趣的功能,这些功能在Scala上目前还不存在,但只有通过全面实现函数式编程才能得到这些好处。如果您打算这样做,那么Clojure很可能更好。如果不打算这样做,那么您应该选择Scala。


9
Clojure 的函数式编程功能是我考虑使用这种语言的最有说服力的原因。我已经到了这个地步了:如果我不用函数式方式编写代码,那我为什么还要费心在嵌入到 Java 中的脚本语言上呢?我已经有 Python 来完成快速而粗略的任务了。 - Ryan Delucchi
"嵌入Java的脚本语言"。这个翻译准确地传达了原始文本的含义,同时还包括了“embedded”的意思,即这种脚本语言嵌入在Java中使用。 - Jus12
@Daniel:抱歉让你产生了困惑。我是指针对Ryan Delucchi的评论。他说Scala是“嵌入Java的脚本语言”,但我不认同这种说法。(除非他是指Clojure,但我对此一无所知)。 - Jus12
@Jus12 我理解他是把这些语言作为JVM脚本语言使用,而且鉴于这一点,除非他转向函数式编程,否则他不认为它们比Python更有优势。当然,我不是他,所以只能猜测一下。 - Daniel C. Sobral

20

请注意,Clojure和Scala是两种完全不同类型的编程语言 - Clojure是一种函数式的类Lisp语言,它不是面向对象的。而Scala是一种面向对象的语言,具有函数式编程的特性。

在我看来,语言的特性和概念(如函数式、面向对象等)比性能(特定实现的性能)更重要的选择语言的标准 - 尽管我理解你不想陷入没有良好性能实现的语言中。

如果你想学习面向对象,并且也希望学习函数式编程,那么我会选择Scala。另一方面,如果你不关心面向对象,想要学习“纯”的函数式编程,那么试试Clojure。


9
显然你没有使用过Clojure。 Clojure 的面向对象程度与 Scala 的函数式程度差不多。你可以实现接口,扩展类,声明私有和静态函数等(http://clojure.org/java_interop)。 - Richard Clayton
30
Clojure中存在这些东西是为了与Java进行互操作,但类和对象显然不是Clojure的主要特性。如果你要用Clojure编程,就不需要创建类或以面向对象的方式设计项目。 - Jesper
问题在于:当你深入一个项目时,发现性能很差,并且不仅仅是因为一个小部分(你已经计划将其转换为Java),那么会发生什么?虽然我并不打算在这里说“不要使用Clojure - 完全不要使用...”,但应该清楚的是,在性能领域,Clojure是一个更大的风险。有很多应用程序级别的代码可以不考虑性能问题,但也有很多框架/多线程/处理密集型代码库,其中Clojure将成为一种负担。 - WestCoastProjects
@javadba 认为 Clojure 不适合低级多线程代码的想法似乎相当武断。Clojure 的设计使得多线程编程错误非常难以发生。不可变数据和 STM 特性是 Clojure 语言的核心,这些特性在 Scala 核心中不可用,并且它们使得程序员意外地将竞争条件或死锁插入到他们的代码 更不可能 。毫无疑问,这比像 Scala 或 Java 这样的静态类型语言可能获得的几毫秒运行时间更有价值。 - nben
当数据规模变大时,几毫秒的运行时间就显得微不足道了。这比运行时间更有价值。 - WestCoastProjects

19
  1. Idiomatic Scala比idiomatic Clojure更快,而且将保持这样。
  2. Scala和Clojure都可以轻松地运行在Java之上,但是在Java下面运行不佳。

如果你的代码在时间或空间方面十分关键,请坚持使用Java。但即使你认为是这样,实际上也不是。

计算机语言基准测试游戏很少揭示Clojure真正的资源成本。没有使用Clojure数据结构。也没有使用函数和序列抽象。

Clojure可能看起来很简单。实际上并不是这样,但它很富有表现力。它可能比Java慢五倍,但是源代码却小了五倍(你的情况可能会有所不同)。对于大多数应用程序来说,这是一个巨大的优势。但对于一些应用程序的某些部分来说,这是一个毁灭性的损失。

通过对Clojure语言的经验,我相信您可以事先确定您的问题是否能够清晰地划分为一个可以用Clojure简洁而充分(在性能方面)表达的部分,以及一个需要在Java中完成的部分。

  • 您可以选择Scala lite:在Scala中编写Java惯用语。您将获得一些简洁性,一个对眼睛更加友好的语法,以及一个连贯但复杂的类型系统。
  • 不存在Clojure lite:在Clojure中编写Java惯用语是完全无意义的。所有你会得到的就是慢的Java代码,因为它与用于表达它的惯用语相矛盾而难以理解。

Scala被称为“正确地完成了Java”。Clojure与Java毫不相同。你可能会说它是Lisp做的对 - 一个大胆的、有些可笑的说法 - 可能会被证明是真的。


4
这个回答很好地阐明了这两者的真正区别和优劣。它既不是偏向于 Scala 也不是偏向于 Clojure,而是以真实的方式写成的。 - WestCoastProjects

15

"计算机语言基准测试大赛"(Computer Language Benchmark Game)产生的统计数据可能是您能找到的最好的。

这些数据非常详细,您可以比较很多编程语言。问题在于它们没有涵盖Clojure :(

尽管如此,提交任何内容都相当容易-它全部是开源的。

这些统计数据表明Scala非常快。


9
这就是了。比Java慢2-25倍,内存使用量和代码大小通常比Java大2-30倍。看起来它与Python相当,而Scala非常接近Java。我会说Scala是一个相当明显的赢家,而Clojure则明显较慢——除非Clojure测试编写得很差。 - Bill K
2
看起来基准测试现在已经涵盖了Clojure(OP的评论已经一年了)。而且结果并不令人鼓舞。Scala是正确的选择。 - Martin
4
上面的评论有些过时了 - 截至2012年中期,Clojure已经大大缩小了与Java之间的差距,现在平均只有Java的两倍左右。 - mikera

9
关于互操作性,我不能代表Clojure发言,但我预计它的情况与Scala类似。
从Scala调用Java非常容易。
只要将你的外部API符合Scala和Java之间的共同点,从Java调用Scala也很容易。例如,Scala对象在某些方面类似于Java的静态方法,但并不完全相同。Scala类可能会编译成多个在Java中看起来有点奇怪的类。
你不会想要混合使用太多。使用大量Java库构建Scala或Clojure组件是非常可行的。当然,你可以从Java调用这个组件,但你不会想尝试从Java消费一个供Scala程序使用的Scala API。
SVN声称自己是“正确实现的CVS”。在我看来,Scala是正确实现的Java。

1
@Ron 哈哈,我也是这么想的。 - KoW
2
实际上,Clojure的集合类似于Git。 - Joe Lehmann

2

PragPub 2010年11月刊的文章讨论了Clojure-Java互操作性。调用Java方法很简单,但扩展Java类/接口则有所不同。

而Scala则更接近于Java。 Scala-Java互操作性在http://www.codecommit.com/blog/java/interop-between-java-and-scala中有详细介绍。

调用Java代码和扩展Java类/接口的方式与调用Scala代码相同。一些痛点可能是处理Java泛型的一些边缘情况,因为Scala的类型系统比Java更强大。按照Java Bean约定创建getter和setter需要使用注释

从Java调用Scala通常很简单,但例如Scala的伴生对象需要知道它们如何编译成字节码。此外,使用具有非抽象方法的traits应该很复杂,并且调用具有特殊字符的方法需要知道它们在字节码中如何编码。


1

现在(截至2010年5月),值得关注Clojure的最新1.2分支 - 这包括对原始类型和静态类型的大量额外支持(通过各种类型提示和协议)。

我的理解是,当您需要时,可以使用这些功能以获得与纯Java编写完全相同代码的速度等效。


2
同时,在即将发布的Scala 2.8版本中,“@specialized”技术也为Scala库带来了类似的改进。作为一种语言工具,它适用于所有代码,而不仅仅是标准库。 - Randall Schulz

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