代码之家  ›  专栏  ›  技术社区  ›  ad absurdum

为什么不同调用按时间报告的消耗字节数不同?

  •  0
  • ad absurdum  · 技术社区  · 6 年前

    Common-Lisp:一种交互式方法 ,和计时a reverse 函数应用于10000个元素的列表。当我使用相同的列表计时此函数时 time 函数报告每次使用的字节数不同。

    这是 颠倒 功能:

    (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 '()))
    

    (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
    

    第二次和第三次测试运行(间隔几分钟)显示的字节数相同,但其他两次显示的字节数不同。我原以为时间会改变,但没想到使用的字节数会改变。我看到超啄鸟说 time 功能:

    一般来说,这些时间不能保证足够可靠 目的。

    但我希望这适用于计时,而不是字节计数。字节消耗值是否由 时间 不可靠的?幕后是否有一个优化机制对此负责?我错过了什么?

    0 回复  |  直到 6 年前
        1
  •  5
  •   tfb    6 年前

    考虑的数量(以“已分配内存的字节数”为单位)取决于一切:

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

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