haskell - para - Creación de perfiles con pila
update haskell (3)
¿Cómo le digo a stack
que -prof
mi ejecutable y todas sus dependencias con -prof
?
Simplemente agregarlo a ghc-options
en el archivo .cabal
no es suficiente, ya que solo intenta compilar el ejecutable con el perfil habilitado, que falla.
Creación de perfiles con Stack 1.0.0 y versiones posteriores
Para compilar con perfiles habilitados:
stack build --profile
Es posible que tengas que ejecutar la stack clean
primero , pero esto debería arreglarse en la Pila 1.5.0 .
Al perfil:
stack exec -- <your program> +RTS <profiling options>
donde para las <profiling options>
es posible que desee -p
para -p
perfiles de tiempo o -h
para -h
perfiles de memoria. Para perfiles de tiempo, el perfil aparece en ./<your program>.prof
y para el perfil de memoria, el perfil aparece en ./<your program>.hp
.
Consulte la documentación de perfiles de GHC para obtener más opciones de perfiles.
Evitar la reconstrucción innecesaria de paquetes locales
Debido a un problema de pila de larga duración , el cambio entre compilaciones de creación de perfiles y sin perfil puede provocar una gran cantidad de reconstrucción innecesaria de paquetes locales y extra-deps
. Para solucionar esto, puede usar cachés de compilación separados para sus compilaciones de generación de perfiles y sin perfil. Por ejemplo, donde usa stack <cmd>
para no crear perfiles puede usar
stack --work-dir .stack-work-profile --profile <cmd>
para una versión de perfil de <cmd>
. Esto utiliza un caché separado en .stack-work-profile
para perfilar artefactos, mientras que los artefactos que no son de perfil se conservarán en el caché de .stack-work
predeterminado.
Creación de perfiles con versiones Stack anteriores a la 1.0.0 (es decir, desde 2015)
Para compilar con perfiles habilitados:
stack build --executable-profiling --library-profiling --ghc-options="-fprof-auto -rtsopts"
Al perfil:
stack exec -- <your program> +RTS <profiling options>
Ejemplo para Stack 1.0.0 y más reciente
Supongamos que tiene un paquete llamado test
con una única test
ejecutable definida por main
aquí:
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
luego haciendo stack build --profile && stack exec -- test +RTS -p
producirá un archivo ./test.prof
que incluye
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
Es decir, hay información de perfil para todas las definiciones, incluidas las definiciones locales en cláusulas where
.
Si solo quieres perfilar las definiciones de nivel superior, puedes compilar con la opción GHC -fprof-auto-top
lugar: haciendo stack build --profile --ghc-options=-fprof-auto-top && stack exec -- test +RTS -p
produce un ./test.prof
que incluye
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
en lugar.
Finalmente, tenga en cuenta que stack build --profile
también activa rastreos de pila. Si cambia el programa para que barSubSub x = error $ show x
, entonces ejecutar stack build --profile && stack exec test
produce
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>)
¡Muy genial!
Para la stack build
, el stack bench
y la stack test
, puedes usar stack build/bench/test --profile
. Es posible que tenga que stack clean
primero para que vuelva a compilarse con los perfiles.
Para la stack build
, igual tendrá que pasar +RTS -p
o la opción que necesite (consulte la Guía del usuario de GHC ) al ejecutar el ejecutable como en la respuesta @ Tomáš Janoušek .
También puede encontrar más información en la sección de depuración de la guía de usuario de la pila .
También tuve este problema y descubrí que el problema estaba en la invocación:
stack exec my-exe +RTS -p
pasa -p a stack en lugar de my-exe. Esto funciona:
stack exec -- my-exe +RTS -p