Профилирование частично оцененной программы
В целях профилирования частично оцененной программы мне интересно узнать, как лучше всего завершить программу GHC. Это полезно для профилирования программ, выполнение которых может занять много времени, возможно, до бесконечности.
С GHC 7.4.2 я смог профилировать программу без прерывания, включив профилирование (-prof -auto-all) и запустив мою программу с +RTS -p
, Это генерирует данные инкрементного профилирования. Программа может быть убита с ^c
и файл.prof будет содержать данные. В GHC 7.6 и более поздних версиях кажется, что если программа может быть завершена одним ^c, то информация о профилировании записывается на выход. Однако (особенно в новых версиях GHC?) Одиночный ^ c не убивает программу, по крайней мере, пока я не потерял терпение и снова нажал ^ c. Обычно два ^ c убивают программу, но тогда никакие данные профилирования не записываются на выход.
Конкретно рассмотрим проблему попытки профилировать StupidFib.hs:
fib n = fib (n - 1) + fib (n - 2)
main = print $ fib 100
Скомпилировав с помощью -prof и запустив с помощью +RTS -p, я могу убить эту программу одним ^ c за первые примерно 10 секунд выполнения, но после этого только два ^ c выполнят эту работу. Глядя на мои ресурсы, это изменение, похоже, совпадает с программой, использующей всю мою физическую память и перемещающейся в пространство подкачки, однако это может быть случайным.
Почему ^ иногда работает, но не в той же программе? Какой самый простой способ гарантировать, что данные профилирования будут напечатаны, когда программа не завершит свою работу самостоятельно?
1 ответ
Скорее всего, второй сигнал доставляется до того, как программа закончила обработку первого, и в этот момент действие сигнала было сброшено до действия по умолчанию, которое (для SIGINT) должно завершить программу. Из-за перестановки существует значительный интервал, прежде чем код профилирования может записать данные профилирования, в течение которых программа уязвима для второго SIGINT.
Мораль истории: будь терпелив. Если вы будете ждать достаточно долго, программа завершит работу и данные будут записаны. Что касается этой второй C, скажите себе: "Только не делай этого!":-)
Можно утверждать, что среда выполнения Haskell должна устанавливать параметры сигнала таким образом, чтобы второй SIGINT игнорировался, но это было бы рискованно, потому что не было бы простого способа завершить программу, если что-то действительно испортится, пытаясь обработать сигнал.
Вы, вероятно, также хотите избегать программ, которые превышают физическую память и вызывают много перестановок. В этот момент ваши вычисления фактически застопорились, и нет смысла продолжать. использование +RTS -M
ограничить размер кучи, чтобы избежать попадания в эту ситуацию.