Есть например такой код:
(loop repeat 10
do (time
(let ((x 0))
(dotimes (i 250000000)
(incf x 1.0)))))
(loop repeat 10
do (time
(let* ((x 0)
(lock (make-lock))
(th1 (make-thread (lambda ()
(let ((s 0))
(dotimes (i 83333333)
(incf s 1.0))
(with-lock-held (lock)
(incf x s))))))
(th2 (make-thread (lambda ()
(let ((s 0))
(dotimes (i 83333333)
(incf s 1.0))
(with-lock-held (lock)
(incf x s)))))))
(let ((s 0))
(dotimes (i 83333334)
(incf s 1.0))
(with-lock-held (lock)
(incf x s)))
(join-thread th1)
(join-thread th2)))))
Однопоточная версия выполняется за одно и тоже время. А вот в 3 потока первая итерация:
Evaluation took:
6.108 seconds of real time
10.412651 seconds of total run time (10.200638 user, 0.212013 system)
[ Run times consist of 3.332 seconds GC time, and 7.081 seconds non-GC time. ]
170.48% CPU
12,887,838,719 processor cycles
1,998,156,624 bytes consed
А последняя:
Evaluation took:
9.235 seconds of real time
13.556848 seconds of total run time (13.304832 user, 0.252016 system)
[ Run times consist of 6.408 seconds GC time, and 7.149 seconds non-GC time. ]
146.80% CPU
19,482,702,363 processor cycles
1,997,795,272 bytes consed
Т.е. с каждой итерацией время работы GC растёт! Почему? И почему оно вообще столь велико?
Что любопытно, версия с инкрементом на 1, а не на 1.0 лишена этой проблемы.
Пробовал на sbcl-1.0.55 x86 под Linux на трёх ядерной машине.
В ccl тоже не все хорошо: время работы GC слишком большое (но хоть не растёт).