我刚刚开始学习Clojure。我注意到的第一件事是没有循环。可以,我可以重复。因此,让我们看一下这个函数(来自Practical Clojure):
(defn add-up "Adds up numbers from 1 to n" ([n] (add-up n 0 0)) ([n i sum] (if (< n i) sum (recur n (+ 1 i) (+ i sum)))))
为了在Javascript中实现相同的功能,我们使用如下循环:
function addup (n) { var sum = 0; for(var i = n; i > 0; i--) { sum += i; } return sum; }
计时后,结果如下所示:
input size: 10,000,000 clojure: 818 ms nodejs: 160 ms input size: 55,000,000 clojure: 4051 ms nodejs: 754 ms input size: 100,000,000 clojure: 7390 ms nodejs: 1351 ms
然后,我继续尝试经典的fib(在阅读了此文章之后):
在Clojure中:
(defn fib "Fib" [n] (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))
在js中:
function fib (n) { if (n <= 1) return 1; return fib(n-1) + fib(n-2); }
再次,性能有很大的不同。
fib of 39 clojure: 9092 ms nodejs: 3484 ms fib of 40 clojure: 14728 ms nodejs: 5615 ms fib of 41 clojure: 23611 ms nodejs: 9079 ms
注意我在clojure中使用(时间(fib 40)),因此它忽略了JVM的启动时间。这些都是在MacBook Air(1.86 GHz英特尔酷睿2双核)上运行的。
那么,是什么导致Clojure在这里变慢?为什么人们会说“ Clojure快速”?
在此先感谢您,请不要发火焰。
(set! *unchecked-math* true) (defn add-up ^long [^long n] (loop [n n i 0 sum 0] (if (< n i) sum (recur n (inc i) (+ i sum))))) (defn fib ^long [^long n] (if (<= n 1) 1 (+ (fib (dec n)) (fib (- n 2))))) (comment ;; ~130ms (dotimes [_ 10] (time (add-up 1e8))) ;; ~1180ms (dotimes [_ 10] (time (fib 41))) )
来自2.66ghz i7 Macbook Pro OS X 10.7 JDK 7 64bit的所有数字
如您所见,Node.js被删除了。这与1.3.0 alphas一起使用,但是如果您知道自己在做什么,则可以在1.2.0中实现相同的目的。
在我的机器上,用于添加1e8的Node.js 0.4.8约为990ms,fib 41约为7600ms。
Node.js | Clojure | add-up 990ms | 130ms | fib(41) 7600ms | 1180ms