在SBCL中,有没有一种方法可以对“ COMMON-LISP”程序包中的功能进行概要分析?我基本上是在寻找一种可靠地比较某些内置函数运行时间的方法。例如,可以使用以下功能
(defun doit ()
(dotimes (i 10000000)
(make-list 10 :initial-element 0)
(list 0 0 0 0 0 0 0 0 0 0)))
用于比较make-list
和list
的相对效率(如果已配置)? (请注意,每个函数的汇编代码有所不同。)我在:cl中进行性能分析的尝试带来了底层调试器。
使用sb-ext:get-time-of-day
(可能精确到1微秒)的另一种方法似乎会产生高度可变的结果:
(multiple-value-bind (* usec1) (sb-ext:get-time-of-day)
(dotimes (i 100000000)
(make-list 10 :initial-element 0))
(multiple-value-bind (* usec2) (sb-ext:get-time-of-day)
(dotimes (i 100000000)
(list 0 0 0 0 0 0 0 0 0 0))
(multiple-value-bind (* usec3) (sb-ext:get-time-of-day)
(- (- usec2 usec1) (- usec3 usec2)))))
感谢您提供其他建议。
编辑:这是另一种可能的方法,可以使用探查器来解决较小的时序差异。该示例再次将make-list
与list
进行比较,并得出在多次运行中相当可靠的结果。
* (defun run-make-list ()
(dotimes (i 10000000000)
(make-list 10 :initial-element 0)))
RUN-MAKE-LIST
* (defun run-list()
(dotimes (i 10000000000)
(list 0 0 0 0 0 0 0 0 0 0)))
RUN-LIST
* (defun compare ()
(gc)
(run-make-list)
(run-list))
COMPARE
* (profile "COMMON-LISP-USER")
* (compare)
NIL
* (report)
measuring PROFILE overhead..done
seconds | gc | consed | calls | sec/call | name
----------------------------------------------------
6.532 | 0.000 | 0 | 1 | 6.532000 | RUN-LIST
6.406 | 0.000 | 0 | 1 | 6.406000 | RUN-MAKE-LIST
0.000 | 0.000 | 0 | 1 | 0.000000 | COMPARE
----------------------------------------------------
12.938 | 0.000 | 0 | 3 | | Total
estimated total profiling overhead: 0.00 seconds
overhead estimation parameters:
0.0s/call, 1.4379999e-6s total profiling, 5.98e-7s internal profiling
*
但是,我不确定是否相信结果。循环开销可能会淹没目标比较。
答案 0 :(得分:4)
您可以使用time
:
(time (some-form))
这将运行(some-form)
并打印时间信息。结果与您获得的结果一样可变。
问题在于我们的计算机同时执行许多操作。您的实验可能会受到以下因素的影响:计算机检查邮件,其他一些具有垃圾收集的进程,您自己的具有垃圾收集的进程,网络重新连接,月相等等。
有时候,您至少可以通过以(gc)
开始每个实验来使自己的过程具有更一致的时序。
答案 1 :(得分:2)
SBCL具有统计分析器,并且manual指出:
在common-lisp程序包,SBCL内部或代码中检测开销过大的情况下,对功能进行分析时,您可能会发现sb-sprof比确定性分析器更有用。
答案 2 :(得分:0)
尝试时间功能:
(time(defun doit ()
(dotimes (i 10000000)
(make-list 10 :initial-element 0)
(list 0 0 0 0 0 0 0 0 0 0))))