分析使用堆栈构建

Seb*_*raf 55 haskell cabal haskell-stack

我如何告诉stack构建我的可执行文件及其所有依赖项-prof

只需将它添加到ghc-options了在.cabal文件是不够的,因为它只是试图生成可执行文件与启用分析其失败.

ntc*_*tc2 83

使用Stack 1.0.0及更高版本进行性能分析

要在启用分析的情况下构建:

stack build --profile
Run Code Online (Sandbox Code Playgroud)

您可能需要运行stack clean第一,但是这应该是固定在堆栈1.5.0.

要简介:

stack exec --profile -- <your program> +RTS <profiling options>
Run Code Online (Sandbox Code Playgroud)

其中对于<profiling options>您可能需要-p时间分析或-h内存分析.对于时间分析,配置文件显示在./<your program>.prof内存中,并且对于内存分析,配置文件将显示在./<your program>.hp.

有关更多性能分析选项,请参阅GHC性能分析文档.

避免不必要的重建本地包

由于长期存在的Stack问题,在分析和非分析构建之间切换会导致大量不必要的本地软件包重建extra-deps.要解决此问题,您可以为分析和非分析构建使用单独的构建缓存.例如,stack <cmd>您可以使用非分析的用途

stack --work-dir .stack-work-profile --profile <cmd>
Run Code Online (Sandbox Code Playgroud)

用于分析版本<cmd>.这使用单独的缓存来.stack-work-profile进行分析工件,而非分析工件将保留在默认 .stack-work缓存中.

在1.0.0之前使用Stack版本进行性能分析(即从2015年开始)

要在启用分析的情况下构建:

stack build --executable-profiling --library-profiling --ghc-options="-fprof-auto -rtsopts"
Run Code Online (Sandbox Code Playgroud)

要简介:

stack exec -- <your program> +RTS <profiling options>
Run Code Online (Sandbox Code Playgroud)

Stack 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
Run Code Online (Sandbox Code Playgroud)

那么做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
Run Code Online (Sandbox Code Playgroud)

即,存在所有定义的分析信息,包括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
Run Code Online (Sandbox Code Playgroud)

代替.

最后,请注意,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>)
Run Code Online (Sandbox Code Playgroud)

太酷了!

  • 这不起作用.使用堆栈exec my-exe + RTS -p显示可执行文件尚未使用-prof编译,并且尝试这样做表明ld无法找到库的配置文件版本. (5认同)
  • 从2019年开始你好!今天使用 Stack 2.1.3,这些说明对我不起作用。我还需要将“--profile”添加到“stack exec”调用中。这有效:`stack build --profile &amp;&amp; stack exec --profile -- my-exe +RTS ...` (3认同)
  • 这对我有用:`stack install --enable-executable-profiling --enable-library-profiling --ghc-options =" - fprof-auto -rtsopts"` (2认同)
  • 您能先介绍一下.stack-work-profile`吗?第一次阅读此答案时,我看到并完成了第一行,并在继续阅读后感到后悔。 (2认同)

Tom*_*šek 14

我也有这个问题,发现问题出在调用中:

stack exec my-exe +RTS -p将-p传递给堆栈而不是my-exe.这有效:

stack exec -- my-exe +RTS -p
Run Code Online (Sandbox Code Playgroud)


jpa*_*ath 5

对于stack buildstack bench并且stack test你可以使用stack build/bench/test --profile。您可能必须stack clean首先使它重新与概要分析一起编译。

因为如@TomášJanoušekanswer一样运行可执行文件时,stack build您仍然必须通过+RTS -p或需要任何选项(请参阅GHC用户指南)。

您还可以在堆栈用户指南调试部分中找到更多信息。