繁体   English   中英

使用GHC编译非常大的常量

[英]Compiling very large constants with GHC

今天我要求GHC编译一个8MB的Haskell源文件。 GHC考虑了大约6分钟,吞下了近2GB的RAM,然后最终放弃了内存不足的错误。

[顺便说一句,我很高兴GHC很有意义中止而不是整个PC。]

基本上我有一个程序,它读取文本文件,进行一些奇特的解析,构建数据结构,然后使用show将其转储到文件中。 我不想将整个解析器和源数据包含在我的最终应用程序中,而是希望将生成的数据包含为编译时常量。 通过向show的输出添加一些额外的东西,你可以使它成为一个有效的Haskell模块。 但GHC显然不喜欢编译多MB源文件。

(最奇怪的部分是,如果你刚刚read回数据,它实际上并不需要花费太多时间或内存。奇怪的是,考虑到String I / O和read都被认为非常低效......)

我模糊地回忆起其他人在过去使用GHC编译大文件时遇到了麻烦。 FWIW,我尝试使用-O0 ,它加速了崩溃但没有阻止它。 那么在Haskell程序中包含大型编译时常的最佳方法什么?

(在我的例子中,常量只是一个带有一些有趣标签的嵌套Data.Map 。)

最初我认为GHC可能只是对阅读由一行长达800万个字符组成的模块感到不满。 (!!)与布局规则等有关。 或者深深嵌套的表达式可能会扰乱它。 但我尝试将每个子表达式作为顶级标识符,这没有任何帮助。 (然而,为每个人添加显式类型签名确实会使编译器更加愉快。)还有什么我可能会尝试使编译器的工作更简单吗?

最后,我能够使我实际上试图存储的数据结构小得多。 (比如300KB。)这让GHC更加快乐。 (最后的应用程序要快得多。)但是为了将来参考,我有兴趣知道最好的方法是什么。

您最好的选择可能是将值的字符串表示形式编译到可执行文件中。 要以干净的方式执行此操作,请参阅上一个问题中的答案

要使用它,只需将表达式存储在myExpression.exp ,并在启用QuasiQuotes扩展时read [litFile|myExpression.exp|] ,并将表达式“存储为可执行文件中的字符串文字”。


我尝试做类似的事情来存储实际的常量,但它失败的原因与在.hs文件中嵌入值相同。 我的尝试是:

Verbatim.hs

module Verbatim where

import Language.Haskell.TH
import Language.Haskell.TH.Quote
import Language.Haskell.Meta.Parse

readExp :: String -> Q Exp
readExp = either fail return . parseExp

verbatim :: QuasiQuoter
verbatim = QuasiQuoter { quoteExp = readExp }

verbatimFile :: QuasiQuoter
verbatimFile = quoteFile verbatim

测试程序:

{-# LANGUAGE QuasiQuotes #-}
module Main (main) where

import Verbatim

main :: IO ()
main = print [verbatimFile|test.exp|]

此程序适用于小型test.exp文件,但在此计算机上已经失败,大约2MiB。

有一个简单的解决方案 - 你的文字应该有ByteString类型。 有关详细信息,请参阅https://github.com/litherum/publicsuffixlist/pull/1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM