我以为我会构建一个愚蠢的非尾递归版本的乘法函数,看看它与正确的TCO比较。但是我注意到REPL(我正在使用配置为java -cp <classpath> clojure.main
的{{1}}的Emacs)以及从命令行调用程序时,显然正在进行某种优化/ memoization。实际上,结果在REPL中更为明显。
inferior-lisp
以上是在REPL上产生的:
用户=&GT; #'用户/ MULT傻
用户=&GT; “经过的时间:10.697919 msecs”
20000个
“经过时间:3.069106 msecs”
20000个
“经过的时间:2.301474 msecs”
20000个
“经过的时间:1.285696 msecs”
20000个
“经过的时间:0.585541 msecs”
20000
我知道为什么会看到这个?
答案 0 :(得分:4)
正如@MariusDanila在评论中指出的那样,这是由于JIT的推动。
要验证这一点,您可以使用-Xint
选项运行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
正如你在第二种情况中所看到的,没有加速。
这就是微基准测试的Rule 1始终排除测量的预热时间的原因。