我最近一直在嘗試Clojure。我嘗試編寫我自己的地圖功能(實際上是兩個),並對照內置函數對它們進行計時。然而,我的地圖功能比內置功能要慢得多。我想知道如何讓我的實現更快。它應該給我一些我編寫的性能調優Clojure算法的見解。第一個函數(my-map)用遞歸進行遞歸。第二個版本(my-map-loop)使用循環/遞歸,這比簡單地使用遞歸要快得多。使我的Clojure地圖功能實現更快
(defn my-map
([func lst] (my-map func lst []))
([func lst acc]
(if (empty? lst)
acc
(recur func (rest lst) (conj acc (func (first lst)))))))
(defn my-map-loop
([func lst]
(loop [acc []
inner-lst lst]
(if (empty? inner-lst)
acc
(recur (conj acc (func (first inner-lst))) (rest inner-lst))
))))
(let [rng (range 1 10000)]
(time (map #(* % %) rng))
(time (my-map #(* % %) rng))
(time (my-map-loop #(* % %) rng)))
這是我得到的結果 -
"Elapsed time: 0.084496 msecs"
"Elapsed time: 14.132217 msecs"
"Elapsed time: 7.324682 mess"
更新
resueman指出,我是不正確的時間的事情後,我改變了功能:
(let [rng (range 1 10000)]
(time (doall (map #(* % %) rng)))
(time (doall (my-map #(* % %) rng)))
(time (doall (my-map-loop #(* % %) rng)))
nil)
這些是新的結果:
"Elapsed time: 9.563343 msecs"
"Elapsed time: 12.320779 msecs"
"Elapsed time: 5.608647 mess"
"Elapsed time: 11.103316 msecs"
"Elapsed time: 18.307635 msecs"
"Elapsed time: 5.86644 mess"
"Elapsed time: 10.276658 msecs"
"Elapsed time: 10.288517 msecs"
"Elapsed time: 6.19183 mess"
"Elapsed time: 9.277224 msecs"
"Elapsed time: 13.070076 msecs"
"Elapsed time: 6.830464 mess"
看起來像我的第二個實現是最快的一堆。無論如何,我仍然想知道是否有辦法進一步優化它。
請注意在JVM上使用'time'進行基準測試。 JIT預熱可對結果產生重大影響。 '時間'可以提供一階近似,但如果您真的關心精度,最好使用像Criterium這樣的適當基準框架(與其中一個答案相關)。 –