javascript - 如何提高 ClojureScript 的性能

标签 javascript clojure clojurescript

我最近开始使用 ClojureScript。当我将 JavaScript 程序重写为 ClojureScript 时,我担心 ClojureScript 的性能。

ClojureScript 代码

(def NUM 10000)
(def data
  (vec (repeatedly NUM #(hash-map :x (rand) :y (rand)))))

(.time js/console "cljs")
(loop [x 0 y 0 d data]
  (if (empty? d)
    [x y]
    (recur (+ x (:x (first d)))
           (+ y (:y (first d)))
           (rest d))))
(.timeEnd js/console "cljs")

编译后的 JavaScript 代码(优化:空白)

benchmark_cljs.benchmark.NUM = 1E4;
benchmark_cljs.benchmark.data = cljs.core.vec.call(null, cljs.core.repeatedly.call(null, benchmark_cljs.benchmark.NUM, function() {
  return cljs.core.PersistentHashMap.fromArrays.call(null, [new cljs.core.Keyword(null, "x", "x", 1013904362), new cljs.core.Keyword(null    , "y", "y", 1013904363)], [cljs.core.rand.call(null), cljs.core.rand.call(null)]);
}));
console.time("cljs");
var x_4753 = 0;
var y_4754 = 0;
var d_4755 = benchmark_cljs.benchmark.data;
while (true) {
  if (cljs.core.empty_QMARK_.call(null, d_4755)) {
    new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [x_4753, y_4754], null);
  } else {
    var G__4756 = x_4753 + (new cljs.core.Keyword(null, "x", "x", 1013904362)).cljs$core$IFn$_invoke$arity$1(cljs.core.first.call(null, d    _4755));
    var G__4757 = y_4754 + (new cljs.core.Keyword(null, "y", "y", 1013904363)).cljs$core$IFn$_invoke$arity$1(cljs.core.first.call(null, d    _4755));
    var G__4758 = cljs.core.rest.call(null, d_4755);
    x_4753 = G__4756;
    y_4754 = G__4757;
    d_4755 = G__4758;
    continue;
  }
  break;
}
console.timeEnd("cljs");

JavaScript 代码

var NUM = 10000;
var data = [];
for (var i = 0; i < NUM; i++) {
  data[i] = {
    x: Math.random(),
    y: Math.random()
  }
}
console.time('js');
var x = 0;
var y = 0;
for (var i = 0; i < data.length; i++) {
  x += data[i].x;
  y += data[i].y;
}
console.timeEnd('js');

ClojureScript 代码和 JavaScrpt 代码做同样的事情,但每个处理时间不同。

处理时间

ClojureScript(optimizations :whitespace): 30 〜 70ms
ClojureScript(optimizations :advanced): 9 〜 13ms
JavaScript: 0.3ms 〜 0.9ms

请告诉我如何改进 ClojureScript 的处理时间。

提前致谢。

最佳答案

您在 ClojureScript 中使用持久数据结构,在 JavaScript 中使用可变数组和对象。预计这两个代码段的性能特征会有所不同。

现在,如果性能对您所做的事情非常重要并且持久性没有任何好处,您可以只使用 ClojureScript 中的数组和对象:

(def NUM 10000)
(def data (array))
(loop [i 0]
  (when (< i NUM)
    (aset data i (js-obj "x" (js/Math.random) "y" (js/Math.random)))
    (recur (inc i))))

(let [lim (alength data)]
  (loop [x 0 y 0 i 0]
    (if (< i lim)
      (recur (+ x (aget data i "x"))
             (+ y (aget data i "y"))
             (inc i))
      (println x y))))

另一方面,如果您确实需要保留所涉及的数据结构的旧版本,您可能会因为不必制作完整副本来保存它们而赢回“失去的时间”。

关于javascript - 如何提高 ClojureScript 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21721028/

相关文章:

clojure - 将项目 -> 类别向量的 clojure 映射解析为分类列表

javascript - 漂亮地打印不可读的 ClojureScript #js 表单

javascript - 如何防止我的数组在 React JS 中的 onChange 函数上一次又一次地更新?

javascript - Jquery 换行符删除在 Firefox 中不起作用

Clojure 从 Java 翻译过来

clojure - (chan) 和 (chan 1) 和有什么不一样?

clojurescript - 无法通过优化构建 ClojureScript 快速入门

javascript - (JavaScript) 将数据从较大的数组存储到具有其他关键属性的较小数组

JavaScript:对类/函数和对象使用相同的名称?

emacs - 在 Emacs 中为 Clojure 设置 SLIME 和 Inferior-Lisp