Runhaskell表现异常

Ste*_*eve 8 haskell runhaskell

我正在尝试理解在运行程序时观察到的性能异常runhaskell.

该计划是:

isFactor n = (0 ==) . (mod n)
factors x = filter (isFactor x) [2..x]
main = putStrLn $ show $ sum $ factors 10000000
Run Code Online (Sandbox Code Playgroud)

当我运行它时,需要1.18秒.

但是,如果我重新定义isFactor为:

isFactor n f = (0 ==) (mod n f)
Run Code Online (Sandbox Code Playgroud)

然后该程序需要17.7秒.

这是性能上的巨大差异,我希望程序是等效的.有人知道我在这里缺少什么吗?

注意:在GHC下编译时不会发生这种情况.

Joh*_*n L 9

虽然功能应该相同,但它们的应用方式有所不同.使用第一个定义,isFactor完全应用于呼叫站点isFactor x.在第二个定义中,它不是,因为现在isFactor显式地采用两个参数.

即使是最小的优化也足以让GHC看到这一点并为两者创建相同的代码,但是如果你编译-O0 -ddump-simpl就可以确定,没有优化,这会产生影响(至少与ghc-7.2.1,YMMV与其他版本一致) ).

对于第一个isFactor,GHC创建一个单独的函数,作为谓词传递给"GHC.List.Filter",调用mod 10000000(==)内联.对于第二个定义,相反的是,大多数调用isFactor都是对类函数的let-bound引用,并且不在多个调用之间共享isFactor.所以有很多字典开销是完全没必要的.

这几乎从来都不是问题,因为即使是默认的编译器设置也会对它进行优化,但是runhaskell显然甚至没有这么做.即便如此,我偶尔会编写代码,someFun x y = \z ->因为我知道这someFun将部分应用,这是保持调用之间共享的唯一方法(即GHC的优化器不够聪明).


Mat*_*hid 5

据我了解,runhaskell几乎没有优化.它旨在快速加载和运行代码.如果它进行了更多优化,则代码开始运行需要更长时间.当然,在这种情况下,代码运行得更快,优化更快.

据我了解,如果存在编译版本的代码,那么runhaskell将使用它.因此,如果性能对您很重要,请确保首先打开优化进行编译.(我想你甚至可以通过开关runhaskell打开优化 - 你必须检查文档...)