我有一个小的测试框架。它执行一个循环,执行以下操作:
runhaskell执行此操作。该程序生成各种磁盘文件。这种情况发生了几十次。事实证明,runhaskell占用了程序执行时间的绝大部分。
一方面,runhaskell设法从磁盘加载文件、对其进行解析、进行依赖分析、从磁盘加载更多20 is的文本、对所有这些进行完整的类型推断、检查类型、从desugar到Core、针对编译的机器代码进行链接,以及在解释器中执行这些操作,这些都是在墙时间的2秒内完成的,当您想到它时,实际上是非常令人印象深刻的。另一方面,我还是想让它跑得更快。;-)
编译测试器(运行上述循环的程序)产生了很小的性能差异。编译脚本链接所针对的20 of的库代码产生了更明显的改进。但每次调用runhaskell仍要花费大约1秒时间。
生成的Haskell文件每个仅超过1KB,但文件的一个部分实际上发生了变化。也许编译文件和使用GHC的-e开关会更快?
或者,可能是重复创建和破坏许多OS进程的开销正在减慢速度?每次对runhaskell的调用都可能导致操作系统探索系统搜索路径,找到必要的二进制文件,将其加载到内存中(这肯定已经在磁盘缓存中了?),将其链接到任何DLL,并启动它。有什么方法可以(很容易)让GHC的一个实例运行,而不是不断地创建和破坏OS进程?
最终,我想总会有GHC。但据我所知,这是可怕的难以使用,高度无文件,并容易发生根本性的变化,在每一个微小的点发布的GHC。我想要完成的任务非常简单,所以我并不想让事情变得过于复杂。
有什么建议吗?
更新:切换到GHC -e (即,除了正在执行的一个表达式外,现在所有内容都已编译)没有显著的性能差异。在这一点上似乎很清楚,这一切都是操作系统开销。我想知道我是否可以创建一个从测试器到GHCi的管道,从而使用一个OS进程.
发布于 2012-02-17 14:39:37
好的,我有一个解决方案:我创建了一个GHCi进程,并将它的stdin连接到一个管道上,这样我就可以将它的表达式发送给交互式计算。
几个相当大的程序重构之后,整个测试套件现在大约需要8秒来执行,而不是48秒。那对我来说就行了!:-D
(对任何试图这么做的人来说:看在上帝的份上,记得把-v0开关传给GHCi,否则你会得到一个GHCi欢迎横幅!)奇怪的是,如果您以交互方式运行GHCi,即使使用-v0,命令提示符仍然会出现,但是当连接到管道时,命令提示符就会消失;我认为这是一个有用的设计特性,而不是随机的意外。)
当然,我之所以沿着这条奇怪的路线走下去,一半原因是我想将stdout和stderr捕获到一个文件中。使用RunHaskell非常容易;创建子进程时只需传递适当的选项即可。但是现在所有的测试用例都是由一个OS进程运行的,所以没有明显的方法来重定向stdin和stdout。
我想出的解决方案是将所有测试输出定向到单个文件,在测试之间,GHCi打印出一条神奇的字符串(我希望如此!)不会出现在测试输出中。然后退出GHCi,打开文件,寻找神奇的字符串,这样我就可以将文件剪成适当的块。
发布于 2012-06-24 03:46:52
您可能会在TBC中找到一些有用的代码。它有着不同的抱负--尤其是放弃测试样板和可能无法完全编译的测试项目--但它可以通过一个监视目录特性来扩展。这些测试是在GHCi中运行的,但是使用了由cabal成功构建的对象("runghc安装程序构建“)。
我开发它是为了测试带有复杂类型的黑客的EDSLs,即由其他库来完成繁重的计算工作。
我目前正在更新它到最新的Haskell平台,欢迎任何评论或补丁。
发布于 2012-02-17 10:16:25
如果大部分源文件保持不变,则可以使用GHC的-fobject-code (可能与-outputdir一起使用)标志编译一些库文件。
https://stackoverflow.com/questions/9326097
复制相似问题