首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >提高ClojureScript程序的性能

提高ClojureScript程序的性能
EN

Stack Overflow用户
提问于 2013-05-14 16:19:32
回答 2查看 1.6K关注 0票数 8

我有一个ClojureScript程序,主要对集合执行数学计算。它是用惯用的、与主机无关的Clojure开发的,因此很容易对其进行基准测试。令我惊讶的是(与Which is faster, Clojure or ClojureScript (and why)?的答案相反),ClojureScript中相同的代码运行速度比它的Clojure等效代码慢5到10倍。

这就是我所做的。我在http://clojurescript.net/上打开了一个http://clojurescript.net/和一个浏览器服务器。然后,我在两个REPL中尝试了这些片段。

代码语言:javascript
运行
复制
 (time (dotimes [x 1000000] (+ 2 8)))

 (let [coll (list 1 2 3)] (time (dotimes [x 1000000] (first coll))))

然后我在浏览器里打开了一个javascript控制台并编写了一个极简的基准函数,

代码语言:javascript
运行
复制
 function benchmark(count, fun) {
   var t0 = new Date();
   for (i = 0; i < count; i++) {
     fun();
   }
   var t1 = new Date();
   return t1.getTime() - t0.getTime();
 }

返回到浏览器REPL:

代码语言:javascript
运行
复制
 (defn multiply [] (* 42 1.2))

然后在javascript控制台中尝试本地javascript乘法及其clojurescript变体,

代码语言:javascript
运行
复制
 benchmark(1000000, cljs.user.multiply);

 benchmark(1000000, function(){ 42 * 1.2 });

我发现的

  • 本机javascript的数学可与clojure中的数学媲美。
  • ClojureScript比他们任何一个都慢5-10倍。

现在我的问题是,如何提高我的ClojureScript程序的性能?

到目前为止,我已经考虑过一些方法

  • 回到幕后使用可变的javascript数组和对象。(这有可能吗?)
  • 回到使用本机javascript数学运算符。(这有可能吗?)
  • 显式地与(aget js/v 0)一起使用javascript数组
  • 使用一个不那么雄心勃勃的实现,比如https://github.com/chlorinejs/chlorinehttps://github.com/gozala/wisp,它们会生成一个更地道的javascript,但它们不支持名称空间,我经常使用它。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-05-14 19:59:00

JavaScript有显式返回,因此

代码语言:javascript
运行
复制
function () { 42 * 1.2 }

什么也不做,你会想要基准测试

代码语言:javascript
运行
复制
function () { return 42 * 1.2 }

而不是。这恰好是ClojureScript版本编译的内容,因此不会有任何区别(在ClojureScript中,非高阶用法中的基本算术函数被内联为基于常规运算符的JavaScript表达式)。

现在,Clojure在这一点上绝对比ClojureScript快。部分原因是Clojure仍然比ClojureScript更仔细地调优,尽管ClojureScript在这个部门正在以相当大的速度改进。另一部分是Clojure有一个更成熟的JIT来利用(现代的JS引擎,特别是V8,非常棒,但还没有达到热点级)。

然而,衡量这种差异的程度有点棘手;JIT涉及的事实意味着,一个没有任何副作用的循环(比如问题中的那个)很可能会被优化,甚至在第一次运行时也是如此(通过使用HotSpot和V8使用的栈上替换--我认为--我必须检查一下才能确定)。所以,最好做一些基准测试,比如

代码语言:javascript
运行
复制
(def arr (long-array 1))

;;; benchmark this
(dotimes [_ 1000000]
  (aset (longs arr) 0 (inc (aget (longs arr) 0))))

(longs调用以避免在Clojure中进行反射;也可以使用^longs提示)。

最后,对于某些对性能特别敏感的代码,无论是Clojure还是ClojureScript,最好使用本机数组等等。幸运的是,这样做没有问题:在ClojureScript方面,您有arrayjs-objagetasetmake-array,您可以在deftype中的字段中使用:mutable元数据,以便能够在方法体中对它们进行set!等等。

票数 10
EN

Stack Overflow用户

发布于 2013-05-14 20:35:10

ClojureScript数学是JavaScript数学。是的,如果性能非常关键,请使用JavaScript数组和提供的低级操作符,这些操作保证在可能的情况下产生最佳代码(即不使用更高的顺序)。ClojureScript持久化数据结构采用数组变异、算术、位旋转等方式。

我有一个关于高效的ClojureScript - stl/spectral/demo.cljs的小例子,您可能会发现它作为指南很有用。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16548136

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档