【发布时间】:2015-09-04 02:40:36
【问题描述】:
我最近一直在试验 Clojure。我尝试编写自己的地图函数(实际上是两个),并根据内置函数对它们进行计时。但是,我的地图功能比内置地图功能要慢得多。我想知道如何使我的实施更快。它应该让我对我编写的 Clojure 算法的性能调整有一些见解。第一个函数 (my-map) 使用 recur 进行递归。第二个版本 (my-map-loop) 使用 loop/recur 比简单地使用 recur 快得多。
(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"
更新
在救援人员指出我的计时有误后,我将函数更改为:
(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"
看起来我的第二个实现是最快的。无论如何,我仍然想知道是否有进一步优化它的方法。
【问题讨论】:
-
谨防使用
time在JVM 上进行基准测试。 JIT 预热会对结果产生重大影响。time可以提供一阶近似值,但如果您真的关心准确性,最好使用适当的基准测试框架,例如 Criterium(链接到其中一个答案)。
标签: performance clojure functional-programming