Clojure REPL对这段代码做了什么样的优化?

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

我想我会建立一个愚蠢的无尾递归版本的乘法函数,看看它与正确的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 (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编译器的问题。它很可能与自适应优化相结合(代码运行得越多,优化得越积极)。