为什么在不同的通话中TIME报告的已允许字节数不同?

时间:2019-04-14 00:35:58

标签: lisp common-lisp sbcl

使用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值不可靠吗?幕后是否存在对此负责的优化?我想念什么?

1 个答案:

答案 0 :(得分:4)

精简的数量(从“已分配的内存字节数”的角度来看)取决于一切:

  • 这取决于您分配多少类型的对象;
  • 这取决于分配器的详细实现细节,例如分配器是否以大块分配,以及是否记录了分配大块之间的“分配”;
  • 这取决于垃圾收集器-是否触发了垃圾收集器?如果是这样的话? GC有多毛? GC本身会分配吗?如何在GC之间分配分配?
  • 这取决于系统是否正在执行其他分配(例如在其他线程中进行分配),以及该分配是否在您的线程中进行计数-是只有一个分配器还是每个线程的分配器?
  • 这取决于月相以及冥王星是否是行星;
  • 等等。

通常,如果您有一个非常简单的单线程实现,一个非常简单的分配器和一个非常简单的GC,则跟踪分配很容易,并且您将获得可靠的数字。许多Lisp的实现曾经是这样的:它们易于理解,并且您在做任何事情时都必须喝很多茶(好吧,当时的机器速度较慢,但​​即使按时间标准,它们仍然常常令人印象深刻地缓慢)。现在,Lisps具有多个线程,复杂的分配器和GC,它们确实非常快,但是发生多少分配已成为一个难题,很难回答,而且往往有些不可预测。