为什么程序在梯级或分析中会更快?

mad*_*jar 9 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
Run Code Online (Sandbox Code Playgroud)

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

编译时

ghc --make -O2 coding.hs
Run Code Online (Sandbox Code Playgroud)

该计划非常缓慢.然而,-fprof-auto似乎加快了这一切.编译

ghc --make -O2 coding.hs -prof -fprof-auto -fforce-recomp
Run Code Online (Sandbox Code Playgroud)

让它快速燃烧-prof,没有任何影响.

奇怪的是,它在运行时也非常快runghc coding.hs.

我不知道从哪里开始.有谁知道这里发生了什么?

编辑:我应该提到我的ghc是7.10.1.

mad*_*jar 2

提供问题的完整答案:

正如 Reid Barton 提到的,问题似乎是臭名昭著的状态黑客优化,它嵌入mimeMap到重复的 IO 操作中,执行次数远远超过必要的次数。-fno-state-hack禁用该优化并解决问题。解决该问题的另一种方法是强制对``mimeMap.

!mimeMap <- fmap M.fromList $ replicateM n [...]
Run Code Online (Sandbox Code Playgroud)

然而, GHC 7.10 中似乎也存在回归,但并-fno-state-hack不能解决问题。这解释了为什么它没有为我解决这个问题。

非常感谢大家的回答。