clojure - Improve performance of a ClojureScript program -
i have clojurescript program performs math calculations on collections. developed in idiomatic, host-independent clojure, it's easy benchmark it. surprise (and contrary answers suggest which faster, clojure or clojurescript (and why)?), same code in clojurescript runs 5-10 times slower clojure equivalent.
here did. opened lein repl
, browser repl @ http://clojurescript.net/. tried these snippets in both repls.
(time (dotimes [x 1000000] (+ 2 8))) (let [coll (list 1 2 3)] (time (dotimes [x 1000000] (first coll))))
then opened javascript console @ browser repl , wrote minimalist benchmark function,
function benchmark(count, fun) { var t0 = new date(); (i = 0; < count; i++) { fun(); } var t1 = new date(); return t1.gettime() - t0.gettime(); }
back browser repl:
(defn multiply [] (* 42 1.2))
then try both native javascript multiplication, , clojurescript variant in javascript console,
benchmark(1000000, cljs.user.multiply); benchmark(1000000, function(){ 42 * 1.2 });
what found
- native javascript math comparable math in clojure
- clojurescript 5-10 times slower either of them
now question is, how can improve performance of clojurescript program?
there approaches i've considered far
- fall using mutable javascript arrays , objects behind scenes. (is possible @ all?)
- fall using native javascript math operators. (is possible @ all?)
- use javascript arrays explicitly
(aget js/v 0)
- use less ambitious implementation of clojure-for-javascript, https://github.com/chlorinejs/chlorine or https://github.com/gozala/wisp generate more idiomatic javascript, don't support namespaces 'm using lot.
javascript has explicit return, so
function () { 42 * 1.2 }
does nothing; you'll want benchmark
function () { return 42 * 1.2 }
instead. happens clojurescript version compiles to, there won't difference (in clojurescript, basic arithmetic functions in non-higher-order usage inlined regular operator-based javascript expressions).
now, clojure faster clojurescript @ point. part of reason clojure still more tuned clojurescript, although clojurescript improving @ pretty great pace in department. part clojure has more mature jit take advantage of (the modern js engines, v8 in particular, pretty great, not quite hotspot-grade yet).
the magnitude of difference tricky measure, though; fact jits involved means loop body free of side effects, such 1 in question, optimized away, possibly on first run through (through use of on-stack replacement, used hotspot , i think v8 -- i'd have check sure though). so, better benchmark like
(def arr (long-array 1)) ;;; benchmark (dotimes [_ 1000000] (aset (longs arr) 0 (inc (aget (longs arr) 0))))
(longs
call avoid reflection in clojure; use ^longs
hint).
finally, case, in both clojure , clojurescript, kinds of particularly performance-sensitive code it's best use native arrays , such. happily, there's no problem doing so: on clojurescript side, you've got array
, js-obj
, aget
, aset
, make-array
, can use :mutable
metadata on fields in deftype
able set!
them in method bodies etc.
Comments
Post a Comment