【问题标题】:Why are the number of bytes consed reported by TIME differing for different calls?为什么 TIME 报告的字节数因不同的调用而不同?
【发布时间】:2019-04-14 00:35:57
【问题描述】:

使用 SBCL 1.4.12,我正在查看来自 Stuart Shapiro 的Common Lisp: An Interactive Approach 的练习 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 值是否不可靠?幕后是否有对此负责的优化?我错过了什么?

【问题讨论】:

  • 通过在time 之前调用(sb-ext:gc :full t),您的结果差异通常较小,从而消除了测量中的一个“噪音”来源。

标签: lisp common-lisp sbcl


【解决方案1】:

consing 的数量(在“分配的内存字节”的意义上)取决于一切:

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

一般来说,如果你有一个非常简单的单线程实现,带有一个非常简单的分配器和一个非常简单的 GC,那么跟踪分配很容易,你会得到可靠的数字。许多 Lisp 实现曾经是这样的:它们很容易理解,而且当它们做任何事情时你必须喝很多茶(好吧,当时机器速度较慢,但​​即使按照当时的标准,它们仍然常常慢得令人印象深刻)。现在 Lisps 有多个线程、复杂的分配器和 GC,而且它们的速度非常快,但是发生了多少分配已经成为一个很难回答并且通常有点难以预测的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 2021-11-28
    • 2012-05-25
    • 2017-02-04
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多