【问题标题】:Why is "cabal build" so slow compared with "make"?为什么“cabal build”比“make”慢?
【发布时间】:2015-12-10 22:35:35
【问题描述】:

如果我有一个包含多个可执行文件的包,我最初使用cabal build 构建它。现在我更改了一个只影响一个可执行文件的文件,cabal 似乎需要大约一两秒来检查每个可执行文件以查看它是否受到影响。另一方面,make,给定相同数量的可执行文件和源文件,将在几分之一秒内确定需要重新编译的内容。为什么会有巨大的差异?有什么原因吗,cabal 不能只构建自己的 makefile 版本并从那里开始?

【问题讨论】:

  • 请注意,虽然make 将始终重新编译任何依赖于已触摸文件的内容,但cabal build 将不一定重新编译下游模块,如果您只更改文件中的一个函数。它以某种方式发现接口没有受到影响,并且重新链接文件就足够了(这通常比重新编译任何东西快得多)。顺便说一句,我认为我们应该谈论的实际上是ghc -make; cabal 只调用它来检查包中的依赖关系。

标签: haskell build cabal


【解决方案1】:

免责声明:我对 Haskell 或 make 内部结构不够熟悉,无法提供技术细节,但一些网络搜索确实提供了一些符合我的建议的见解(试图通过提供参考来避免引发意见)。另外,我假设您的 makefile 正在调用 ghc,就像 cabal 显然会那样。

建议:我相信可能有几个关键原因,但主要原因是make 是用C 编写的,而cabal 是用Haskell 编写的。这将与来自make 的高级依赖性检查相结合(尽管我不确定如何在不查看源代码的情况下证明这一点)。其他支持原因,如在网上找到的:

  • cabal 尝试做的不仅仅是简单的编译,例如似乎在包装方面采取了措施 (https://www.haskell.org/cabal/)
  • cabal 是用 haskell 编写的,尽管运行时是用 C 编写的 (https://en.wikipedia.org/wiki/Glasgow_Haskell_Compiler)
  • 同样,由于不太熟悉make 内部结构,make 可能只是具有更快的依赖关系检查机制,从而更好地跟踪这些变化。我指出这一点是因为从 OP 看来,与 cabal 可能对所有依赖项进行全面检查的地方存在足够显着的差异。如果属实,我怀疑这将是速度差异的主要原因。

无论如何,这些都是开源的,可以从各自的网站(haskell.org/cabal/ 和 savannah.gnu.org/projects/make/)下载,允许任何人检查实施的细节。

根据传递给正在使用的编译器的开关,人们也可能会看到很多速度差异。

HTH 至少为您指明了正确的方向。

【讨论】:

  • 另见this SO线程;显然 make 对时间戳进行了简单的检查,以判断是否发生了变化。
  • Cabal 看起来像是 bit deeper 的变化,只是由于其运作的性质。
  • 我对@9​​87654333@s 或makes 的内部结构也不太了解,但我相当确信性能差异与前者用Haskell 编写的关系不大。编译后的 Haskell 实际上只比 C 慢一点,前提是您远离某些性能陷阱(严重融合列表、过于懒惰等)。事实上,有时惯用的 Haskell 实现会比没有特别优化的 C 解决方案更快
  • 您可以编辑您的答案以合并新信息或删除被发现不正确的内容(例如相当明显的错误说法,即 Cabal 速度较慢,因为它是用 Haskell 编写的而不是 C)。
  • @dfeuer:正如@leftaroundabout 所指出的,说一个是否更快并不总是那么简单(使用诸如“小”和“有时”之类的词来表示这一点)。尤其是在混合中加入优化(也提出了一个问题:“make 的分布式/发布版本真的会未优化吗?”),需要经验 确定哪个更快以及为什么。查看源代码和编译器优化的水平肯定是其中的一部分。
猜你喜欢
  • 2011-03-23
  • 1970-01-01
  • 2022-07-05
  • 2019-12-18
  • 2015-10-04
  • 2012-09-16
  • 2016-10-06
  • 2020-11-27
  • 2011-10-19
相关资源
最近更新 更多