У меня есть программа ClojureScript, которая в основном выполняет математические вычисления для коллекций. Он был разработан на идиоматическом, независимом от хоста Clojure, поэтому его легко протестировать. К моему удивлению (и вопреки тому, что ответы предложили бы Что быстрее , Clojure или ClojureScript (и почему)?), тот же код в ClojureScript работает в 5-10 раз медленнее, чем его эквивалент в Clojure.
Вот что я сделал. Я открыл lein repl
и ответил в браузере на http://clojurescript.net/. Затем я попробовал эти фрагменты в обоих REPL.
(time (dotimes [x 1000000] (+ 2 8)))
(let [coll (list 1 2 3)] (time (dotimes [x 1000000] (first coll))))
Затем я открыл консоль 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:
(defn multiply [] (* 42 1.2))
Затем попробуйте как собственное умножение javascript, так и его вариант clojurescript в консоли javascript,
benchmark(1000000, cljs.user.multiply);
benchmark(1000000, function(){ 42 * 1.2 });
Что я нашел
- Собственная математика JavaScript сопоставима с математикой в Clojure
- ClojureScript в 5-10 раз медленнее любого из них
Теперь мой вопрос: как мне улучшить производительность моей программы ClojureScript?
Есть несколько подходов, которые я рассмотрел до сих пор
- Вернитесь к использованию изменяемых массивов javascript и объектов за кулисами. (Это вообще возможно?)
- Вернитесь к использованию собственных математических операторов javascript. (Это вообще возможно?)
- Явное использование массивов javascript с
(aget js/v 0)
- Используйте менее амбициозную реализацию clojure-for-javascript, например https://github.com/chlorinejs/chlorine или https://github.com/gozala/wisp Они генерируют более идиоматический javascript, но они не поддерживают пространства имен, которые я часто использую.