站内搜索
 
关于Clojure特性的几点思考
时间:2012-09-24  来源:网络  作者:  阅读人数:2642

摘要:为什么Clojure运行速度这么慢?近日,这一话题在hacker news却引发了开发者们的热议,Clojure在很多方面还是很成功的,但是有一方面却是令人窒息,那就是运行速度。究竟为何会运行慢,本文将为你揭秘,共同来探讨Clojure特性。
导读:最近《Some thoughts on Clojure performance》这篇文章在hacker news却引发了开发者们的热议,主要是因为受其标题的误导“Why is Clojure so slow?”这篇文章是作者Martin Trojer在Rich Hickey's Clojure/Conj 2011大会前便完成的,文中主要谈及了Clojure特性并给出了一些解决方案。

Clojure是JVM上的一门新的语言,类似Groovy,Jyphon和JRuby,它能动态的、简洁的、无缝的与Java进行交互操作。

Clojure在很多方面还是很成功的,但是有一方面却是令人窒息,那就是速度。这里指的是Clojure的运行速度。这是一个众所周知的话题也是开发者们在Stack overflow上经常讨论的话题。我并不打算在这里引发争论,而是想想谈谈因话题而引发的一些思考。

想要测试代码的运行速度非常的棘手,因为会涉及到很多程序问题。尤其是在Clojure程序中JVM,Clojure bootstrapping和动态编译这部分。

但事实上,一些运行工具类似Leiningen (lein) 或“jack-in”速度缓慢,主要是因为Clojure程序需要很长时间来“启动”。此外即使Clojure启动成功并且正在运行,但与JVM相比并不是很快,详情可参考The Computer Language Benchmarks Game测试结果。

你会发现初次运行Clojure启动的时间会很慢。在REPL里运行“Hello world”是非常令人头疼的,这里收集了各种语言在MacBook Pro上运行“Hello world”所需要的时间,这个Macbook Pro配置了2.5GHz的酷睿双核CPU”,一起来看下对比情况:

从图中我们可以看到,Java自身运行时间为0.35s,而Clojure因自身原因又多增添几秒。这1.3s就是前面我们所提及的为什么Clojure不适用于终端脚本语言?任何一种脚本语言(比如lein或者REPL)的运行时间都会受控于启动时间。相比较Clojure程序员,很多Clojure开发者并未没有注意到这些,因为他们大部分时间花在了REPL上。

CLR (mono)的运行速度大约是JVM的4倍。这是“#-py”语言的一个插件。此外,还注意到F#和C#运行速度的差别要小于Clojure和Java之间的差别。因此,没有任何理由或者依据能够说明函数/说明性语言的启动速度要慢于同类型的语言。

那么我们为什么不在mono虚拟机上使用Clojure/CLR呢?这是因为目前Clojure在CLR上启动时间更差,同样的hello world语句运行超过1.8s(使用Clojure/CLR程序集调试)---ClojureCLR和C#与Clojure和Java之间的差异就是数量级变得更糟,也就是说继ClojureCLR项目之后会遗留很多问题。

是什么原因导致运行时间长?

Daniel Solanoconj/2011大会上演示了Clojure和Android(幻灯片),就其性能方面给出了一些有价值的见解以及演示了在Clojure在运行时内部发生了什么。我认为Clojure花了95%的时间用在加载clojure.core命名空间(clojure.lang.RT类)以及填写所有元数据/文档字符串等方法上。在这过程中GC(垃圾回收)便占用不少时间,130K对象分配,90K free-d在调用多个GC(3-6倍)以及基于这个庞大的数据源上创建元数据。

译注:通过使用“-verbose:gc”在clojure上运行进行测试时,我注意到一个子集占用了0.018s,与Daniel的研究结果不同,因为在Dalvik VM性能测试很难发现特别之处。Daniel提出了几点解决方案来改善这种情况,并且这些方案似乎看起来还不错:

  • 使用单独的jar(归档文件)(当在交互式解释器REPL中希望使用所有的文档字符串)并且移除正在运行的jar(注意不要与现有的clojure-slim jar文件混淆)。
  • 连续让clojure.core初始化以便在启动时磁盘清理内存。

ClojureScript的救赎

ClojureScript和Google 超快速的javascript V8引擎是也是另一种不错的方法。当使用ClojureScript编译器编译hello word语句时,我们节省了100KB JavaScript而V8引擎运行的速度为0.140s,以2.5x的速度快于Java版本,9x速度快于Clojure/JVM版本。或许Google Closure编译器给它带来一丝帮助,它能够移除一些无用的代码,以致生成的Javascript文件里剔除了无用的文档。此外,Rich Hickey提到了去年他提出ClojureScript作为"Clojure's script story"的主要好处之一是大大改善了启动时间。

建立与运行

Clojure运行代码后最终会怎样?通过The Computer Language Benchmarks Game我们知道Clojure平均以4x速度慢于Java,2x速度慢于Scala,造成这一结果的最大因素在于Clojure有着不可改变的数据结构。事实上不可变的数据结构要永远慢于可变的数据结构。Clojure连贯性的数据结构与可变的同类数据有着相同的时间复杂度,但是它们的运行速度并不一样快,因为在运行期间不变的时间因素起到了很大作用。大部分以50-200秒为基准,所以Clojure启动的时间是导致这一结果的重要因素。通常情况下动态语言要比静态语言慢。

结论:

以上这些留给我们什么启示呢?Clojure是一门美丽的,强大的,非常有用的语言,但是(目前的版本)并不适用于小的script-y程序中。关于启动时间的问题可以寻求解决方法,你可以以通过改变Clojure语言或者需找新的ClojureScript路径。我个人很喜欢JavaScript(事件)追踪方式,拥有低处理器,可利用的空间比JVM大,使其能更好的使用ClojureScript-scripting。

Clojure的应用范围比较广,常被用于嵌入式系统中。然而为了使ClojureScript能作为非浏览器中一个可行性的选择,如今依然有很多工作要做,尽管现今可以与Node.js相整合,但是先将“:bare”作为编译目标是一个很好的补充,其次在考虑建立一个良好的基于浏览器之外的APIs。

各位网友,你说呢?

发表评论
 留言列表
首页 上一页 下一页 末页 第1/1页 7条/页 共0条记录

Copyright@2018 新疆企业资源计划管理(ERP)生产力促进中心
新ICP备10002072号  地址:乌鲁木齐市高新北区冬融街53号新疆电子研究所股份有限公司5楼研发中心
邮编:830013  电话:(0991)3137684

 您 是 第  位 访 客