Подтвердить что ты не робот

Профилирование сборок с помощью стека

Как сообщить stack о том, как построить мой исполняемый файл и все его зависимости с помощью -prof?

Просто добавить его в ghc-options в файле .cabal недостаточно, потому что он только пытается создать исполняемый файл с включенным профилированием, что не получается.

4b9b3361

Ответ 1

Профилирование сборок с помощью Stack 1.0.0 и новее

Чтобы построить с включенным профилированием:

stack build --profile

Возможно, вам сначала потребуется запустить stack clean, но это должно быть исправлено в стеке 1.5.0.

К профилю:

stack exec --profile -- <your program> +RTS <profiling options>

где для <profiling options> может потребоваться -p для профилирования времени или -h для профилирования памяти. Для профилирования времени профиль отображается в ./<your program>.prof, а для профилирования памяти - в ./<your program>.hp.

См. документацию по профилированию GHC для получения дополнительной информации о профилировании.

Как избежать ненужной перестройки локальных пакетов (исправлено в Stack 2.X?)

Из-за длительного стека Вопрос, переключение между профилирующей и непрофилирующей сборками может вызвать много ненужной перестройки локальных пакетов и extra-deps. Работать вокруг этого вы можете использовать отдельные кэши сборки для своего профилирования и непрофилирующие сборки. Например, где вы используете stack <cmd> для без профилирования вы можете использовать

stack --work-dir .stack-work-profile --profile <cmd>

для профилирующей версии <cmd>. Это использует отдельный кеш в .stack-work-profile для профилирования артефактов, в то время как артефакты без профилирования будут сохранены по умолчанию .stack-work кеш.

Профилирование сборок с использованием версий Stack до 1.0.0 (т.е. с 2015 года)

Чтобы построить с включенным профилированием:

stack build --executable-profiling --library-profiling --ghc-options="-fprof-auto -rtsopts"

В профиль:

stack exec -- <your program> +RTS <profiling options>

Пример для стека 1.0.0 и новее

Предположим, у вас есть пакет под названием test с одним исполняемым файлом test, определенным main здесь:

module Main where

main :: IO ()
main = do
  print $ foo 0

foo :: Int -> Int
foo x = fooSub (x+1)
  where
    fooSub x = bar (x+1)

bar :: Int -> Int
bar x = barSub (x+1)
  where
    barSub x = barSubSub (x+1)
      where
        barSubSub x = x+1

затем выполнение stack build --profile && stack exec -- test +RTS -p создаст файл ./test.prof, который включает в себя

                                                                                                individual      inherited
COST CENTRE                 MODULE                SRC                        no.     entries  %time %alloc   %time %alloc

  [... many lines omitted ...]
  main                      Main                  src/Main.hs:(4,1)-(5,15)    97          0    0.0    0.0     0.0    0.0
   foo                      Main                  src/Main.hs:(8,1)-(10,24)   98          1    0.0    0.0     0.0    0.0
    foo.fooSub              Main                  src/Main.hs:10:5-24         99          1    0.0    0.0     0.0    0.0
     bar                    Main                  src/Main.hs:(13,1)-(17,46) 100          1    0.0    0.0     0.0    0.0
      bar.barSub            Main                  src/Main.hs:(15,5)-(17,46) 101          1    0.0    0.0     0.0    0.0
       bar.barSub.barSubSub Main                  src/Main.hs:17:9-46        102          1    0.0    0.0     0.0    0.0
 main                       Main                  src/Main.hs:(4,1)-(5,15)    95          0    0.0   20.5     0.0   20.5

Т.е., есть информация профилирования для всех определений, включая локальные определения в предложениях where.

Если вы хотите профилировать определения верхнего уровня, вы можете создать с вместо этого опция GHC -fprof-auto-top: выполнение stack build --profile --ghc-options=-fprof-auto-top && stack exec -- test +RTS -p создает ./test.prof, который включает в себя

                                                                                individual      inherited
COST CENTRE MODULE                SRC                        no.     entries  %time %alloc   %time %alloc

 [... many lines omitted ...]
  main      Main                  src/Main.hs:(4,1)-(5,15)    97          0    0.0    0.0     0.0    0.0
   foo      Main                  src/Main.hs:(8,1)-(10,24)   98          1    0.0    0.0     0.0    0.0
    bar     Main                  src/Main.hs:(13,1)-(17,46)  99          1    0.0    0.0     0.0    0.0
 main       Main                  src/Main.hs:(4,1)-(5,15)    95          0    0.0   20.5     0.0   20.5

вместо этого.

Наконец, обратите внимание, что stack build --profile также включает стек следы. Если вы измените программу так, чтобы barSubSub x = error $ show x, то запуск stack build --profile && stack exec test выдает

test: 4
CallStack (from HasCallStack):
  error, called at src/Main.hs:17:23 in main:Main
CallStack (from -prof):
  Main.bar.barSub.barSubSub (src/Main.hs:17:9-36)
  Main.bar.barSub (src/Main.hs:(15,5)-(17,36))
  Main.bar (src/Main.hs:(13,1)-(17,36))
  Main.foo.fooSub (src/Main.hs:10:5-24)
  Main.foo (src/Main.hs:(8,1)-(10,24))
  Main.main (src/Main.hs:(4,1)-(5,15))
  Main.CAF:lvl8_r4Fc (<no location info>)

Довольно круто!

Ответ 2

У меня также была эта проблема, и я обнаружил, что проблема была в вызове:

stack exec my-exe +RTS -p передает -p в стек вместо my-exe. Это работает:

stack exec -- my-exe +RTS -p

Ответ 3

Для stack build, stack bench и stack test вы можете просто использовать stack build/bench/test --profile. Возможно, вам придется stack clean сначала перекомпилировать его с профилированием.

Для stack build вам все равно придется пройти +RTS -p или любой другой параметр (см. Руководство пользователя GHC) при запуске как в @Tomáš Janoušek ответить.

Вы также можете найти дополнительную информацию в разделе отладки руководства пользователя по стеклу.

Ответ 4

Предполагая, что проект называется project-name, я получаю профиль времени и кучи (с цветами):

  1. Добавить зависимости в раздел build-depends project-name.cabal
  2. Получить зависимые пакеты: stack build
  3. Изнутри project-name/app скомпилируйте программу с включенным профилированием: stack ghc -- -prof -fprof-auto -rtsopts -O2 Main.hs
  4. Затем создайте профиль кучи и времени ./Main +RTS -hc -p. Это будет производить Main.hp и Main.prof
  5. Превратите профиль кучи в файл PostScript, а затем в диаграмму PDF с цветами: stack exec -- hp2ps -c Main.hp && ps2pdf Main.ps

Это куча профиля из PDF:

heap_profile_with_colors