.prof 报告中的 .(...) 是什么意思?
What does .(...) mean in a .prof report mean?
我正在通过使用 -prof
编译来寻找 Haskell 程序中的优化机会,但我不知道如何解释包含省略号的成本中心。什么是 filter.(...)
和 jankRoulette.select.(...)
?
COST CENTRE MODULE %time %alloc
filter.(...) Forest 46.5 22.3
set-union Forest 22.5 4.1
cache-lookup Forest 16.0 0.1
removeMany MultiMapSet 3.7 1.9
insertMany MultiMapSet 3.3 1.8
jankRoulette.select.(...) Forest 1.4 15.2
我生成的是:$ ghc --make -rtsopts -prof -auto-all main.hs && ./main +RTS -p && cat main.prof
函数 filter
在 where
子句中有一些定义,如下所示:
filter a b = blahblah where
foo = bar
bar = baz
baz = bing
但这些都显示为 filter.foo
、filter.bar
等
我认为它们可能是嵌套的 let 表达式,但 jankRoulette.select
没有。而且我在其中大多数之前添加了 SCC 指令,而没有任何成本中心上升到顶部。
由于大部分时间都花在 filter.(...)
上,我想知道那是什么。 :)
TL; DR: 当你在 let 绑定中进行模式匹配时,GHC 会生成这个,比如 let (x,y) = c
。评估 c
的成本由 ...
成本中心跟踪(因为它没有唯一的名称)`。
我是怎么发现的?
GHC 源代码中 (...)
的 grep 找到以下内容(来自 compiler/deSugar/Coverage.hs):
-- TODO: Revisit this
addTickLHsBind (L pos (pat@(PatBind { pat_lhs = lhs, pat_rhs = rhs }))) = do
let name = "(...)"
(fvs, rhs') <- getFreeVars $ addPathEntry name $ addTickGRHSs False False rhs
{- ... more code following, but not relevant to this purpose
-}
该代码告诉我们它必须对模式绑定做一些事情。
所以我们可以制作一个小测试程序来检查行为:
x :: Int
(x:_) = reverse [1..1000000000]
main :: IO ()
main = print x
然后,我们可以运行这个程序启用分析。事实上,GHC 生成以下输出:
COST CENTRE MODULE no. entries %time %alloc %time
%alloc
MAIN MAIN 42 0 0.0 0.0 100.0 100.0
CAF Main 83 0 0.0 0.0 100.0 100.0
(...) Main 86 1 100.0 100.0 100.0 100.0
x Main 85 1 0.0 0.0 0.0 0.0
main Main 84 1 0.0 0.0 0.0 0.0
事实证明,根据代码所做的假设是正确的。程序的所有时间都花在计算 reverse [1..1000000000]
表达式上,并且它被分配到 (...)
成本中心。
我正在通过使用 -prof
编译来寻找 Haskell 程序中的优化机会,但我不知道如何解释包含省略号的成本中心。什么是 filter.(...)
和 jankRoulette.select.(...)
?
COST CENTRE MODULE %time %alloc
filter.(...) Forest 46.5 22.3
set-union Forest 22.5 4.1
cache-lookup Forest 16.0 0.1
removeMany MultiMapSet 3.7 1.9
insertMany MultiMapSet 3.3 1.8
jankRoulette.select.(...) Forest 1.4 15.2
我生成的是:$ ghc --make -rtsopts -prof -auto-all main.hs && ./main +RTS -p && cat main.prof
函数 filter
在 where
子句中有一些定义,如下所示:
filter a b = blahblah where
foo = bar
bar = baz
baz = bing
但这些都显示为 filter.foo
、filter.bar
等
我认为它们可能是嵌套的 let 表达式,但 jankRoulette.select
没有。而且我在其中大多数之前添加了 SCC 指令,而没有任何成本中心上升到顶部。
由于大部分时间都花在 filter.(...)
上,我想知道那是什么。 :)
TL; DR: 当你在 let 绑定中进行模式匹配时,GHC 会生成这个,比如 let (x,y) = c
。评估 c
的成本由 ...
成本中心跟踪(因为它没有唯一的名称)`。
我是怎么发现的?
GHC 源代码中 (...)
的 grep 找到以下内容(来自 compiler/deSugar/Coverage.hs):
-- TODO: Revisit this
addTickLHsBind (L pos (pat@(PatBind { pat_lhs = lhs, pat_rhs = rhs }))) = do
let name = "(...)"
(fvs, rhs') <- getFreeVars $ addPathEntry name $ addTickGRHSs False False rhs
{- ... more code following, but not relevant to this purpose
-}
该代码告诉我们它必须对模式绑定做一些事情。 所以我们可以制作一个小测试程序来检查行为:
x :: Int
(x:_) = reverse [1..1000000000]
main :: IO ()
main = print x
然后,我们可以运行这个程序启用分析。事实上,GHC 生成以下输出:
COST CENTRE MODULE no. entries %time %alloc %time
%alloc
MAIN MAIN 42 0 0.0 0.0 100.0 100.0
CAF Main 83 0 0.0 0.0 100.0 100.0
(...) Main 86 1 100.0 100.0 100.0 100.0
x Main 85 1 0.0 0.0 0.0 0.0
main Main 84 1 0.0 0.0 0.0 0.0
事实证明,根据代码所做的假设是正确的。程序的所有时间都花在计算 reverse [1..1000000000]
表达式上,并且它被分配到 (...)
成本中心。