今天我让 GHC 编译了一个 8MB 的 Haskell 源文件。GHC 考虑了大约 6 分钟,吞噬了将近 2GB 的 RAM,然后最终以 out-of-memory 错误放弃。
[顺便说一句,我很高兴 GHC 有很好的判断来中止而不是让我的整个 PC 瘫痪。]
基本上,我有一个程序可以读取文本文件,进行一些花哨的解析,构建数据结构,然后将show
其转储到文件中。我不想将整个解析器和源数据包含在我的最终应用程序中,而是将生成的数据作为编译时常量包含在内。通过在 的输出中添加一些额外的东西show
,你可以使它成为一个有效的 Haskell 模块。但是 GHC 显然不喜欢编译多 MB 的源文件。
(最奇怪的部分是,如果您只是read
返回数据,它实际上并不需要太多时间或内存。奇怪的是,考虑到String
I/O 和read
据说都非常低效......)
我隐约记得过去其他人在让 GHC 编译大文件时遇到了麻烦。FWIW,我尝试使用-O0
,它加速了崩溃但并没有阻止它。那么在 Haskell 程序中包含大型编译时常量的最佳方法是什么?
(在我的例子中,常量只是嵌套Data.Map
了一些有趣的标签。)
最初,我认为 GHC 可能只是不喜欢阅读由一行 800 万字符组成的模块。(!!)与布局规则等有关。又或许是深藏不露的表情让它心烦意乱。但是我尝试让每个子表达式都成为顶级标识符,但这并没有帮助。(但是,为每个类型添加显式类型签名确实似乎使编译器更快乐。)还有什么我可以尝试使编译器的工作更简单的吗?
最后,我能够使我实际上试图存储的数据结构更小。(比如,300KB。)这让 GHC 更快乐。(最终应用程序要快得多。)但为了将来参考,我很想知道解决这个问题的最佳方法是什么。