【发布时间】:2019-10-22 17:55:54
【问题描述】:
Clojure 中的单个循环/递归执行速度与 Java for 循环等效
Clojure 版本:
(defn singel-loop [i-count]
(loop [i 0]
(if (= i i-count)
i
(recur (inc i)))))
(time (loop-test 100101))
"Elapsed time: 0.8857 msecs"
Java 版本:
long s = System.currentTimeMillis();
for (i = 0; i < 100000; i++) {
}
System.out.println("Time: " + (System.currentTimeMillis() - s));
时间:~1ms
但是,如果您添加一个内部loop/recur,性能绝对会一落千丈!
Clojure:
(defn double-loop [i-count j-count]
(loop [i 0]
(loop [j 0]
(if (= j j-count)
j
(recur (inc j))))
(if (= i i-count)
i
(recur (inc i)))))
(time (double-loop 100000 100000))
"Elapsed time: 70673.9189 msecs"
Java 版本:
long s = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
for (int j = 0; j < 100000; j++) {
}
}
System.out.println((System.currentTimeMillis() - s));
时间:~3ms
为什么 Clojure 版本的性能下降到可笑的程度,而 Java 版本保持不变?
【问题讨论】:
-
顺便说一句。这是一种可怕的微基准测试方法。使用标准之类的东西至少可以获得一些信心。你永远不应该使用
System.currentTimeMillis来衡量一段代码的运行时间。甚至 clojure 的timez usesSystem.nanoTime.currentTimeInMillis` 在虚拟化环境中也可能特别错误。另见stackoverflow.com/questions/8853698/… 和shipilev.net/blog/2014/nanotrusting-nanotime