Почему количество обработанных байтов, сообщаемое TIME, отличается для разных вызовов? - PullRequest
3 голосов
/ 14 апреля 2019

Используя SBCL 1.4.12, я смотрю на Упражнение 17.9 из Common Lisp Стюарта Шапиро: интерактивный подход и определение времени для функции 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, ненадежными? Есть ли за кадром оптимизация, которая за это отвечает? Чего мне не хватает?

1 Ответ

4 голосов
/ 14 апреля 2019

Количество обработки (в смысле «выделено байтов памяти») зависит от всего:

  • это зависит от того, сколько объектов каких типов вы выделите;
  • это зависит от мелких деталей реализации распределителя, таких как то, распределяется ли он большими порциями и записано ли «распределение» между выделением больших порций;
  • это зависит от сборщика мусора - был ли он запущен? если да то какой? насколько волосатый GC? сам ГК выделяет? как подсчитывается распределение по GC?
  • это зависит от того, выполняет ли система другое распределение, например, в других потоках, и учитывается ли это распределение в вашем потоке - есть только один распределитель или есть распределители на поток?
  • это зависит от фазы Луны и от того, является ли Плутон планетой;
  • и т. Д.

В общем, если у вас очень простая однопотоковая реализация с очень простым распределителем и очень простым GC, то отслеживать распределение легко и вы получите надежные числа. Многие реализации Lisp когда-то были такими: их было легко понять, и вам приходилось пить много чая, когда они что-то делали (хорошо, машины тогда работали медленнее, но все же они часто были впечатляюще медленными даже по меркам времени). Теперь в Лиспе есть несколько потоков, сложных распределителей и GC, и они действительно быстрые, но объем распределения стал вопросом, на который очень сложно ответить и который часто слегка непредсказуем.

...