使用@sds 答案中的一些技巧,我意识到有一些简单的初步测试可以回答我针对特定实现的问题(无需通过dissemble
输出)。mapcar
看起来 SBCL 和 CCL 的处理方式不一定与忽略 ' 的返回值mapc
时相同。mapcar
首先将lis1
和定义lis2
为重要长度的列表(我的长度为 100,000,并且包含整数),然后在它们上运行mapcar
,mapc
等多次,如下所示(可选的初步调用gc
以清除旧垃圾):
(gc :full t)
(time
(progn
(dotimes (ignored 1000)
(mapcar #'+ lis1 lis2))
(format t "mapcar:~%")))
(gc :full t)
(time
(progn
(dotimes (ignored 1000)
(mapc #'+ lis1 lis2))
(format t "mapc:~%")))
(gc :full t)
(time
(progn
(dotimes (ignored 1000)
(map nil #'+ (the list lis1) (the list lis2)))
(format t "map nil with lists~%")))
例如,我机器上的 SBCL 产生:
mapcar:
Evaluation took:
2.306 seconds of real time
2.287627 seconds of total run time (2.136130 user, 0.151497 system)
[ Run times consist of 0.147 seconds GC time, and 2.141 seconds non-GC time. ]
99.22% CPU
3,683,188,504 processor cycles
1,600,049,536 bytes consed
mapc:
Evaluation took:
0.639 seconds of real time
0.638733 seconds of total run time (0.638011 user, 0.000722 system)
100.00% CPU
1,020,310,296 processor cycles
0 bytes consed
map nil with lists
Evaluation took:
0.592 seconds of real time
0.592114 seconds of total run time (0.591199 user, 0.000915 system)
100.00% CPU
945,957,944 processor cycles
0 bytes consed
这些是使用默认优化设置的典型结果。使用declaim
来优化速度、非安全性等可以稍微加快速度,但不会改变mapc
andmap nil
比mapcar
, 快一个数量级的事实,这mapcar
会带来很多麻烦。CCL 的结果相似,但总体速度较慢。