haskell - 加速 runhaskell

标签 haskell ghc

我有一个小型测试框架。它执行一个循环,执行以下操作:

  • 生成一个小的 Haskell 源文件。
  • 使用 runhaskell 执行此操作.该程序生成各种磁盘文件。
  • 处理刚刚生成的磁盘文件。

  • 这种情况发生了几十次。原来runhaskell占用了程序绝大部分的执行时间。

    一方面,runhaskell设法从磁盘加载文件,对其进行标记,对其进行解析,进行依赖性分析,从磁盘加载 20KB 以上的文本,标记并解析所有这些,执行完整的类型推断,检查类型,对核心进行脱糖,链接编译的机器代码,并在解释器中执行该操作,所有时间都在 2 秒的墙上时间之内,当您考虑它时,实际上非常令人印象深刻。另一方面,我仍然想让它走得更快。 ;-)

    编译测试器(运行上述循环的程序)产生了微小的性能差异。编译脚本链接的 20KB 库代码产生了相当显着的改进。但是每次调用 runhaskell 仍然需要大约 1 秒.

    生成的 Haskell 文件每个都刚刚超过 1KB,但实际上只有文件的一部分发生了变化。也许编译文件并使用 GHC 的 -e切换会更快吗?

    或者,也许是重复创建和销毁许多操作系统进程的开销减慢了速度?每次调用 runhaskell大概会导致操作系统探索系统搜索路径,找到必要的二进制文件,将其加载到内存中(肯定这已经在磁盘缓存中?),将其链接到任何 DLL,然后启动它。有什么方法可以(轻松)保持 GHC 的一个实例运行,而不必不断创建和销毁操作系统进程?

    最终,我想总会有 GHC API。但据我了解,这非常难以使用,高度无证,并且在 GHC 的每个小版本发布时都容易发生根本性的变化。我试图执行的任务非常简单,所以我真的不想让事情变得比必要的更复杂。

    建议?

    更新:切换到 GHC -e (即,现在除了正在执行的一个表达式之外的所有内容都已编译)没有可测量的性能差异。在这一点上似乎很清楚,这都是操作系统开销。我想知道我是否可以创建一个从测试仪到 GHCi 的管道,从而只使用一个操作系统进程......

    最佳答案

    好的,我有一个解决方案:我创建了一个 GHCi 进程并连接了它的 stdin到管道,以便我可以将表达式发送到交互式评估。

    后来进行了几次相当大的程序重构,整个测试套件现在大约需要 8 秒来执行,而不是 48 秒。这对我有用! :-D

    (对于其他尝试这样做的人:看在上帝的份上,记得将 -v0 切换到 GHCi,否则您会收到 GHCi 欢迎横幅!奇怪的是,如果您以交互方式运行 GHCi,即使使用 -v0命令提示符仍然出现,但是当连接到管道时,命令提示符消失了;我认为这是一个有用的设计功能,而不是随机事故。)

    当然,我走这条奇怪路线的一半原因是我想捕获stdoutstderr到一个文件。使用 RunHaskell ,这很容易;只需在创建子进程时传递适当的选项。但是现在所有的测试用例都由单个操作系统进程运行,所以没有明显的方法来重定向 stdinstdout .

    我想出的解决方案是将所有测试输出定向到单个文件,并且在测试之间让 GHCi 打印出一个魔术字符串(我希望!)不会出现在测试输出中。然后退出 GHCi,下载文件,然后寻找魔法字符串,这样我就可以将文件剪切成合适的 block 。

    关于haskell - 加速 runhaskell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9326097/

    相关文章:

    haskell - 差异列表的显式纯函数数据结构

    haskell - GHC 垃圾收集器/运行时如何知道它可以创建数组 `inplace'

    haskell - GHC:插入编译日期

    haskell - 具有相关函数的最小完整定义

    parsing - 如何使用 BNFC 定义 INI 文件语法?

    math - Haskell 和二次方程

    haskell - 如何在 Haskell 平台中降级 cabal 版本?

    多线程和 gtk2hs

    debugging - 在 GHCi 调试器中中断并继续,而不使用断点

    haskell - 使用 RecordDotSyntax 更新记录会导致错误