haskell 程序在进行性能分析时运行良好,在不进行性能分析时运行较慢

fcwjkofz  于 2023-02-23  发布在  其他
关注(0)|答案(2)|浏览(135)

我观察到以下执行时间:

  • 使用stack build编译时约为9秒
  • 使用stack build --profile编译时约5秒

我希望未分析的执行时间低于1秒,这说明上面的分析时间是有意义的,是未分析的时间异常慢。
更多细节:

  • 该程序读取类似关系代数的DSL,应用一系列基于规则的转换,并将转换结果输出到SQL。解析使用megaparsec完成。I/O基于String,并且相对较小(~ 150 KB)。我会排除I/O作为问题的来源。转换涉及ADT上的递归重写规则。在少数情况下,我使用ugly-memo来加速这种递归重写。
  • 使用带有LTS 18.28、ghc 8.10.7的堆栈2.9.1

编辑:升级到LTS 20.11、ghc 9.2.5没有帮助)

  • 在阴谋集团的档案里:
ghc-options:        -O2 -Wall -fno-warn-unused-do-bind -fno-warn-missing-signatures -fno-warn-name-shadowing -fno-warn-orphans
  ghc-prof-options:   -O2 -fprof-auto "-with-rtsopts=-p -V0.0001 -hc -s"
  • 请注意,以上这些都不是新的,但我以前从未观察过这种行为。
  • 我看过this related question,但是用-fno-state-hack编译没有帮助
  • 使用-O1编译没有帮助(与-O2差不多),并且-O0明显更慢,正如预期的那样。
  • 分析信息显示没有问题。只有在未分析的执行时才会出现此问题。

我知道我没有提供太多细节。特别是,我没有包括任何代码片段,因为它是一个很大的代码库,我不知道它的哪一部分可以触发这种行为。我的意思是,我确实不知道如何缩小它。
所以我的问题不是“问题出在哪里",而是:考虑到显而易见的工具(分析)在这种情况下是无用的,我能做些什么来更接近问题的根源呢?

zujrkrfu

zujrkrfu1#

虽然我仍然不知道概要文件和非概要文件执行之间的差异的确切原因,但现在我在代码中找到了罪魁祸首。
在ADT上递归的函数实现如下:

f :: (?env :: Env) => X -> Y
f = memo go
where
  go :: (?env :: Env) => X -> Y
  go (...) = ...
  go x = f (children x) -- memoised recursion over x's children

请注意:

  • 每次递归都被记忆,因为它的数据结构可能包含许多副本
  • 这个函数使用了一个Env参数,这个参数在内部使用,但在整个递归过程中不会改变。注意,它被声明为隐式参数。

关于这个函数的分析信息显示了比预期更多的函数调用。比预期多了三个数量级!(尽管如此,仍然很奇怪,分析执行相当快)。
结果,隐式参数是个问题,我不知道确切的原因,但我读过关于隐式参数有多邪恶的博客,现在我有了第一手的证据。
将此函数更改为仅使用显式参数完全修复了此问题:

f :: Env -> X -> Y
f env = memo (go env)
where
  go :: Env -> X -> Y
  go env (...) = ...
  go env x = f env (children x) -- memoised recursion over x's children
    • 编辑:**感谢@leftaroundabout指出我上面的解决方案不是很正确--它没有充分利用记忆功能(见下面的讨论)。正确的版本应该是:
f :: Env -> X -> Y
f env = f_env
where 
  f_env = memo $ go env
  go env (...)
  go env x = f_env (children x)

隐式参数似乎导致uglymemo无法识别先前存储的调用,因此我得到了所有随之而来的开销,但没有任何好处。
我的问题算是解决了,但是如果有人能解释隐式参数导致这种行为的潜在原因,以及为什么概要执行会更快,我仍然非常有兴趣了解这一点。

ux6nzvsh

ux6nzvsh2#

这听起来很矛盾:"所以我的问题不是"问题出在哪里",而是:我能做些什么来更接近问题的根源"
在调试器下运行它,在9或5的时候手动暂停它。这样做几次。堆栈会告诉你它是如何浪费时间的,不管是否是I/O。这就是this technique.
你有什么可失去的?

相关问题