Как я уже упоминал в своем комментарии, я не могу дублировать эти медленные показатели производительности, но я почти уверен, что знаю, что происходит. Если вы предоставите дополнительную информацию, которая позволит мне продублировать проблему, я могу обновить ответ.
Скорее всего, список [1..]
(или, возможно, какое-то более крупное выражение, включающее этот список) "поднимается" как постоянная аппликативная форма (CAF) на верхний уровень. Поскольку список генерируется во время этой первой итерации, он сохраняется как «постоянный» объект кучи для будущих итераций.
Первая итерация занимает много времени в части , потому что она выделяет и генерирует список, хотя из-за "распределителя ударов" GHC, распределение происходит очень быстро, и фактически генерация списка, вероятно, занимает всего несколько секунд. Большую часть времени, скорее всего, тратят на сбор мусора. Время GC масштабируется с размером «важного» материала, который необходимо спасти (скопировать) из распределителя бампа, и вы создаете здесь большой постоянный список.
Более поздние итерации намного быстрее, потому что они могут выполнять суммирование Conduit по существующему списку. Вероятно, это требует некоторого распределения промежуточных результатов, но большинство из них не задерживаются, поэтому GC намного меньше, и итерации бывают быстрыми.
Причина, по которой вторая и третья итерации немного медленнее, чем более поздние, связана с сборщиком мусора GHC. Первоначально и постоянный большой список, и другие полупостоянные (например, необходимые только на короткое время или для текущей итерации) объекты кучи копируются из распределителя ударов. Дальнейшая сборка мусора включает повторное копирование того же постоянного списка, в то же время позволяя собирать просроченные полупостоянные объекты. В конечном итоге список переносится в следующее поколение, а все объекты, не входящие в список, остаются в первом поколении.
После того, как постоянный список и полупостоянные «другие объекты» полностью разделены на разные поколения, список больше не нужно переписывать во время GC первого поколения, и время итерации уменьшается примерно до секунды.