Как реализована поддержка среды выполнения ghc для профилирования?

Я не нашел много документации в комментариях. Есть ли хорошие сообщения в блоге или аналогично по этому поводу?

Ответ 1

Лучшим источником информации о структуре профилирования может по-прежнему являться оригинальная статья Патрика Сансом и Саймона Пейтона Джонса. Дополнительную информацию можно найти в Sansom кандидатскую диссертацию, а также более позднюю статью, добавив официальную спецификацию. Саймон Марлоу также рассказал о нескольких недавних изменениях в обновлении статуса GHC на Мастерской исполнителей Haskell 2011.

Идея профилирования затрат-центра состоит в том, чтобы аннотировать дерево выражений узлами "МВЗ", поэтому, например, с помощью -auto-all программа будет иметь аннотации, подобные следующим:

fib n = {-# SCC foo #-} (case n of
                           0 -> 0
                           1 -> 1
                           n -> fib (n-1) + fib (n-2))

Во время выполнения при входе fib программа будет смотреть на текущий "стек центра затрат" и добавить "foo" в начало. Это будет отменено после того, как оценка снова выйдет из области аннотации SCC. Немного магии гарантирует, что если, скажем, n окажется ленивым значением, и программе необходимо выполнить его код, тогда необходимый МВД, соответствующий этому коду, будет восстановлен.

Эта инфраструктура затем используется как для временного, так и для пространственного профилирования:

  • Таймер будет периодически проверять стек МВЗ. Каждый раз, когда обнаруживается определенный стек МВЗ, это считается "тиком". В итоге РТС будет оценивать количество времени на стек затрат-центра из числа его тиков, предоставляя вам профиль времени.

  • Каждый раз, когда объект распределяется, программа сохраняет назад указатель на стек МВЗ, который был текущим в этот момент времени. Это позволяет сборщику мусора предоставить статистику о том, сколько байтов было резидентным, с разбивкой по месту размещения.

Как указано в комментарии, несколько слов об оптимизации: по очевидным причинам структура не может позволить оптимизациям, которые перемещают непостоянные затраты из одного центра затрат в другое, заставляя оптимизатора быть довольно пессимистичным время от времени. Например, в приведенном выше примере текущая версия GHC не сможет отменить возвращаемое значение, что означает, что каждый рекурсивный вызов делает ненужное распределение кучи.

Как правило, нельзя рассчитывать на какие-либо преобразования кода, происходящие в аннотации SCC. Если вы сомневаетесь, лучше записать функцию, достаточно высокую в стеке вызовов, так что критически важные биты вообще не будут аннотированы.

Ответ 2

Вы можете найти эту статью Джонсом, Марлоу и Сингхом, в зависимости от того, что вы хотите выполнить. Он включает практики профилирования программ GHC в параллельном контексте и содержит некоторые тематические исследования, которые могут вам пригодиться.