How to improve ClojureScript performance
clojure, clojurescript, javascript
Solution
You're using persistent data structures in ClojureScript and mutable arrays and objects in JavaScript. It is to be expected that the performance characteristics of the two snippets will be different.
Now, if performance is really critical to what you're doing and persistence provides no benefit, you can just use arrays and objects from 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))))
On the other hand, if you do need to hold on to old versions of the data structures involved, you'll probably win back your "lost time" by not having to make complete copies to preserve them.
Problem
I start using ClojureScript recently. When I rewrote a JavaScript program to ClojureScript, I worried about performace of ClojureScript. ClojureScript code ``` (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") ``` Compiled JavaScript Code (optimizations :whitespace) ``` 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 code ``` 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 code and JavaScrpt code are doing same things but each process time are different. Process time ``` ClojureScript(optimizations :whitespace): 30 〜 70ms ClojureScript(optimizations :advanced): 9 〜 13ms JavaScript: 0.3ms 〜 0.9ms ``` Please tell me how to improve processing time of ClojureScript. Thanks in advance.