Clojure REPL对这段代码做了什么样的优化?
我想我会建立一个愚蠢的无尾递归版本的乘法函数,看看它与正确的TCO函数相比如何。然而,我注意到,无论是在REPL(我使用Emacs和Clojure REPL对这段代码做了什么样的优化?,clojure,Clojure,我想我会建立一个愚蠢的无尾递归版本的乘法函数,看看它与正确的TCO函数相比如何。然而,我注意到,无论是在REPL(我使用Emacs和java-cp clojure.main配置为低级lisp),还是从命令行调用程序时,显然都在进行某种优化/记忆。事实上,结果在REPL中更加明显 (defn mult-silly [n m] (if (> n 0) (+ m (mult-silly (dec n) m)) 0)) (dotimes [_ 5] (println (t
java-cp clojure.main
配置为低级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上产生:
用户=>#“用户/多用户”用户=>“运行时间:10.697919毫秒”
20000
“运行时间:3.069106毫秒”
20000
“运行时间:2.301474毫秒”
20000
“运行时间:1.285696毫秒”
20000
“运行时间:0.585541毫秒”
两万
知道我为什么会这样吗?正如@MariusDanila在评论中指出的,这是由于JIT的影响 要验证这一点,您可以使用
-Xint
选项运行java,这会使java在
仅解释模式,因此不会将任何内容编译为本机代码(当然也不会进行优化)
对该本机代码执行)
下面是我在正常运行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
正如您在第二种情况中看到的,没有加速
这就是为什么微基准测试总是从测量中排除预热时间。可能是JIT编译器的问题。它很可能与自适应优化相结合(代码运行得越多,优化得越积极)。