使用SBCL 1.4.12,我正在看Stuart Shapiro的 Common Lisp:一种交互式方法中的练习17.9,并对{10,000}元素中的reverse
函数进行了计时。当我使用相同的列表对这个函数进行计时时,time
函数每次都会报告不同数量的字节。
以下是reverse
函数的代码:
(defun reverse2 (l1 l2)
"Returns a list consisting of the members of L1 in reverse order
followed by the members of L2 in original order."
(check-type l1 list)
(check-type l2 list)
(if (endp l1) l2
(reverse2 (rest l1)
(cons (first l1) l2))))
(defun reverse1 (l)
"Returns a copy of the list L1
with the order of members reversed."
(check-type l list)
(reverse2 l '()))
我通过以下方式在REPL中生成了列表:
(defvar *test-list* '())
(dotimes (x 10000)
(setf *test-list* (cons x *test-list*)))
以下是四个测试运行的结果:
CL-USER> (time (ch17:reverse1 *test-list*))
Evaluation took:
0.000 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
100.00% CPU
520,386 processor cycles
145,696 bytes consed
CL-USER> (time (ch17:reverse1 *test-list*))
Evaluation took:
0.000 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
100.00% CPU
260,640 processor cycles
178,416 bytes consed
CL-USER> (time (ch17:reverse1 *test-list*))
Evaluation took:
0.000 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
100.00% CPU
279,822 processor cycles
178,416 bytes consed
CL-USER> (time (ch17:reverse1 *test-list*))
Evaluation took:
0.000 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
100.00% CPU
264,700 processor cycles
161,504 bytes consed
第二次和第三次测试运行(相隔几分钟)显示cons的字节数相同,但是其他两个显示的数字不同。我希望时间会有所不同,但是我没想到字节数会有所不同。我看到HyperSpec提到了time
函数:
通常,这些时间不能保证足够可靠 营销比较。它们的值主要是启发式的,用于调整 目的。
但是我希望这适用于计时,而不适用于字节数。 time
报告的字节consed值不可靠吗?幕后是否存在对此负责的优化?我想念什么?
答案 0 :(得分:4)
精简的数量(从“已分配的内存字节数”的角度来看)取决于一切:
通常,如果您有一个非常简单的单线程实现,一个非常简单的分配器和一个非常简单的GC,则跟踪分配很容易,并且您将获得可靠的数字。许多Lisp的实现曾经是这样的:它们易于理解,并且您在做任何事情时都必须喝很多茶(好吧,当时的机器速度较慢,但即使按时间标准,它们仍然常常令人印象深刻地缓慢)。现在,Lisps具有多个线程,复杂的分配器和GC,它们确实非常快,但是发生多少分配已成为一个难题,很难回答,而且往往有些不可预测。