Я не нашел много документации в комментариях. Есть ли хорошие сообщения в блоге или аналогично по этому поводу?
Как реализована поддержка среды выполнения 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 в параллельном контексте и содержит некоторые тематические исследования, которые могут вам пригодиться.