为什么不同呼叫的TIME报告的consed字节数不同?

问题描述 投票:3回答:1

使用SBCL 1.4.12,我正在阅读Stuart Shapiro的Common Lisp:交互式方法中的练习17.9,并将reverse函数的计时应用于10,000个元素的列表。当我使用相同的列表计时此函数时,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

第二次和第三次测试运行(相隔几分钟)显示相同的字节数,但其他两个显示不同的数字。我预计时间会有所不同,但我没想到会有多少字节变化。我看到HyperSpec说的是time函数:

一般而言,这些时间并不能保证足够可靠以进行营销比较。它们的价值主要是启发式的,用于调整目的。

但我希望这适用于时间,而不是字节数。 time报告的字节consed值是否不可靠?幕后是否有优化负责?我错过了什么?

lisp common-lisp sbcl
1个回答
4
投票

consing的数量(在“分配的内存字节数”中)取决于所有内容:

  • 它取决于你分配的类型的对象数量;
  • 它取决于分配器的精细实现细节,例如它是否以大块分配,以及是否记录了分配大块之间的“分配”;
  • 它取决于垃圾收集器 - 是一个触发?如果是这样的那种? GC多毛茸茸? GC本身是否分配?如何在GC之间计算分配?
  • 它取决于系统是否正在进行其他分配,例如在其他线程中,以及该分配是否在您的线程中计数 - 是否只有一个分配器或每个线程分配器?
  • 它取决于月球的相位以及冥王星是否是一颗行星;
  • 等等。

一般来说,如果你有一个非常简单的单线程实现,它有一个非常简单的分配器和一个非常简单的GC,那么跟踪分配很容易,你将获得可靠的数字。许多Lisp实现曾经是这样的:它们很容易理解,而且你在做任何事情时都要喝很多茶(好吧,机器比较慢,但即使按照时间标准,它们仍然经常令人印象深刻)。现在Lisps有多个线程,复杂的分配器和GC,它们真的很快,但是分配的数量已经成为一个很难回答的问题,而且往往有些不可预测。

© www.soinside.com 2019 - 2024. All rights reserved.