为什么程序在runghc或分析中更快?

时间:2015-05-09 15:05:37

标签: haskell

我有以下程序需要一个大输入(扩展/ mime映射列表,文件列表)和逐行输出结果(每个文件的mime类型)。

import System.IO
import Control.Monad
import qualified Data.Map as M
import System.FilePath
import Data.Char

main :: IO ()
main = do
    input_line <- getLine
    let n = read input_line :: Int -- Number of elements which make up the association table.
    input_line <- getLine
    let q = read input_line :: Int -- Number Q of file names to be analyzed.

    mimeMap <- fmap M.fromList $ replicateM n $ do
        input_line <- getLine
        let input = words input_line
        let ext = input!!0 -- file extension
        let mt = input!!1 -- MIME type.
        return (map toLower ext, mt)

    replicateM_ q $ do
        fname <- getLine
        let ext = map toLower . drop 1 . takeExtension $ fname
            mime = M.findWithDefault "UNKNOWN" ext mimeMap
        putStrLn mime

程序很慢,所以我开始分析它,我得到了一个奇怪的结果。

使用

编译时
ghc --make -O2 coding.hs

程序很慢。但是,-fprof-auto似乎加速了这一切。用

编译
ghc --make -O2 coding.hs -prof -fprof-auto -fforce-recomp

让它快速燃烧-prof单独没有效果。

奇怪的是,使用runghc coding.hs运行时速度也非常快。

我不知道从哪方面去。有谁知道这里发生了什么?

编辑:我应该提一下,我的ghc是7.10.1。

1 个答案:

答案 0 :(得分:2)

提供问题的完整答案:

正如Reid Barton所提到的,问题似乎是臭名昭着的状态黑客优化,它将mimeMap内联到重复的IO操作中,执行它的次数超过了必要的次数。 -fno-state-hack禁用该优化并解决问题。解决问题的另一种方法是强制严格评估``mimeMap。

!mimeMap <- fmap M.fromList $ replicateM n [...]

但是,似乎还有一个regression in GHC 7.10,其中-fno-state-hack无法解决问题。这就解释了为什么它没有为我解决。

非常感谢大家的回答。