我想我会构建一个乘法函数的愚蠢的非尾递归版本,看看它如何与正确的 TCO 进行比较。然而,我注意到在 REPL(我使用 Emacs 和 java -cp <classpath> clojure.main
配置为 inferior-lisp
)和从命令行调用程序时,显然正在发生某种优化/内存。事实上,结果在 REPL 中更为明显。
(defn mult-silly [n m]
(if (> n 0)
(+ m (mult-silly (dec n) m))
0))
(dotimes [_ 5]
(println (time (mult-silly 5000 4))))
以上在 REPL 上产生:
user=> #'user/mult-silly
user=> "Elapsed time: 10.697919 msecs"
20000
"Elapsed time: 3.069106 msecs"
20000
"Elapsed time: 2.301474 msecs"
20000
"Elapsed time: 1.285696 msecs"
20000
"Elapsed time: 0.585541 msecs"
20000
知道为什么我会看到这个吗?
最佳答案
正如@MariusDanila 在他的评论中指出的那样,这是由于 JIT 的介入。
要验证这一点,您可以使用 -Xint
运行 java选项,这会导致它运行
仅解释模式,因此不会将任何内容编译为 native 代码(当然也没有优化
对 native 代码完成)。
所以这是我正常运行java的内容:
"Elapsed time: 4.175 msecs"
20000
"Elapsed time: 2.548 msecs"
20000
"Elapsed time: 7.746 msecs"
20000
"Elapsed time: 1.919 msecs"
20000
"Elapsed time: 1.72 msecs"
20000
请注意,此处第三次运行的时间实际上增加了。我猜这是由于编译同时发生。
鉴于
-Xint
:"Elapsed time: 31.463 msecs"
20000
"Elapsed time: 30.844 msecs"
20000
"Elapsed time: 30.643 msecs"
20000
"Elapsed time: 29.972 msecs"
20000
"Elapsed time: 30.617 msecs"
20000
正如您在第二种情况下所看到的,没有加速。
这就是为什么Rule 1微基准测试是始终从您的测量中排除预热时间。
关于clojure - Clojure REPL 对这段代码做了什么样的优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18676388/