亩。
现在说真的,没关系。不是这个尺寸的例子。它们都具有相同的复杂性。如果您的代码对您来说不够快,这可能是您最后要看的地方之一。
现在,如果您真的想知道哪个更快,请测量它们。在 SBCL 上,您可以循环调用每个函数并测量时间。既然你有两个简单的功能,time 就足够了。如果您的程序更复杂,profiler 会更有用。提示:如果您的测量不需要分析器,您可能不需要担心性能。
在我的机器(SBCL 64 位)上,我运行了你的函数并得到了这个:
CL-USER> (time (loop repeat 1000 do (factorial_recursion 1000)))
Evaluation took:
0.540 seconds of real time
0.536034 seconds of total run time (0.496031 user, 0.040003 system)
[ Run times consist of 0.096 seconds GC time, and 0.441 seconds non-GC time. ]
99.26% CPU
1,006,632,438 processor cycles
511,315,904 bytes consed
NIL
CL-USER> (time (loop repeat 1000 do (factorial_loop 1000)))
Evaluation took:
0.485 seconds of real time
0.488030 seconds of total run time (0.488030 user, 0.000000 system)
[ Run times consist of 0.072 seconds GC time, and 0.417 seconds non-GC time. ]
100.62% CPU
902,043,247 processor cycles
511,322,400 bytes consed
NIL
将函数放入顶部带有(declaim (optimize speed)) 的文件后,递归时间降至 504 毫秒,循环时间降至 475 毫秒。
如果您真的想知道发生了什么,请在您的函数上尝试dissasemble,看看里面有什么。
再一次,这对我来说似乎不是问题。就个人而言,我尝试使用 Common Lisp 之类的脚本语言来进行原型设计,然后对速度较慢的部分进行分析和优化。从 500 毫秒到 475 毫秒没什么。例如,在一些个人代码中,通过简单地将元素类型添加到数组中,我获得了几个数量级的加速(因此在我的例子中使数组存储空间小了 64 倍)。当然,从理论上讲,重用该数组(在使其更小之后)而不是一遍又一遍地分配它会更快。但是对于我的情况,只需添加:element-type bit 就足够了——更多的变化需要更多的时间才能获得很少的额外收益。也许我很草率,但“快”和“慢”对我来说意义不大。我更喜欢“足够快”和“太慢”。在大多数情况下,您的两个函数都“足够快”(或者在某些情况下两者都“太慢”),因此它们之间没有真正的区别。