使用 Stack 分析构建
Posted
技术标签:
【中文标题】使用 Stack 分析构建【英文标题】:Profiling builds with Stack 【发布时间】:2015-08-20 16:24:22 【问题描述】:如何告诉stack
使用-prof
构建我的可执行文件及其所有依赖项?
仅将其添加到.cabal
文件中的ghc-options
是不够的,因为它只尝试构建启用了分析的可执行文件,但失败了。
【问题讨论】:
【参考方案1】:使用 Stack 1.0.0 和更高版本分析构建
在启用分析的情况下构建:
stack build --profile
您可能需要先运行stack clean
,然后再运行this should be fixed in Stack 1.5.0。
个人资料:
stack exec --profile -- <your program> +RTS <profiling options>
<profiling options>
的位置可能需要 -p
进行时间分析或 -h
进行内存分析。对于时间分析,配置文件出现在./<your program>.prof
,对于内存分析,配置文件出现在./<your program>.hp
。
有关更多分析选项,请参阅 GHC profiling documentation。
避免不必要地重建本地包(在 Stack 2.X 中修复?)
由于long standing Stack
issue,
在分析和非分析构建之间切换可能会导致很多
不必要地重建本地包和extra-deps
。去工作
围绕这一点,您可以使用单独的构建缓存进行分析和
非分析构建。例如,您使用 stack <cmd>
表示
您可以使用的非配置文件
stack --work-dir .stack-work-profile --profile <cmd>
对于<cmd>
的分析版本。这使用了一个单独的
缓存在.stack-work-profile
中用于分析工件,
而默认情况下将保留非分析工件
.stack-work
缓存。
使用 1.0.0 之前的 Stack 版本(即从 2015 年开始)分析构建
在启用分析的情况下构建:
stack build --executable-profiling --library-profiling --ghc-options="-fprof-auto -rtsopts"
个人资料:
stack exec -- <your program> +RTS <profiling options>
堆栈 1.0.0 及更高版本的示例
假设您有一个名为 test
的包,其中包含由 main
定义的单个可执行文件 test
:
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>)
很酷!
【讨论】:
这不起作用。使用 stack exec my-exe +RTS -p 显示可执行文件尚未使用 -prof 编译,尝试这样做表明 ld 找不到库的配置文件版本。 这对我有用:stack install --enable-executable-profiling --enable-library-profiling --ghc-options="-fprof-auto -rtsopts"
@ChrisStryczynski:我刚刚编辑了我的答案。希望对您有所帮助。
你能把.stack-work-profile
的部分放在第一位吗?我第一次阅读这个答案时,我看到了第一行并做到了,然后我读下去就后悔了。
您好,从 2019 年开始!今天使用 Stack 2.1.3,这些说明对我不起作用。我还需要将--profile
添加到stack exec
调用中。这有效:stack build --profile && stack exec --profile -- my-exe +RTS ...
【参考方案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
,在运行@Tomáš Janoušek answer 中的可执行文件时,您仍然需要传递+RTS -p
或您需要的任何选项(请参阅GHC User Guide)。
您还可以在debugging section of the stack user guide 中找到更多信息。
【讨论】:
您也可以在堆栈构建命令的末尾添加“--force-dirty”来强制它重新编译。 你的意思是说stack exec
?【参考方案4】:
假设一个名为 project-name
的项目,这就是我获得时间和堆配置文件(带颜色)的方式:
-
将依赖项添加到
project-name.cabal
的build-depends
部分
获取依赖包:stack build
从project-name/app
内部用profiling enabled编译程序:stack ghc -- -prof -fprof-auto -rtsopts -O2 Main.hs
然后创建heap 和time 配置文件./Main +RTS -hc -p
。这将产生Main.hp
和Main.prof
将堆配置文件转换为PostScript file,然后转换为带有颜色的PDF图表:stack exec -- hp2ps -c Main.hp && ps2pdf Main.ps
这是 PDF 中的堆配置文件:
【讨论】:
@LupusOssorum:我不知道是否有办法将.prof
文件转换为 PDF。但是有.prof
文件的可视化工具,例如profiteur、professor和viewprof。以上是关于使用 Stack 分析构建的主要内容,如果未能解决你的问题,请参考以下文章