我有以下程序需要一个大输入(扩展/ 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。
答案 0 :(得分:2)
提供问题的完整答案:
正如Reid Barton所提到的,问题似乎是臭名昭着的状态黑客优化,它将mimeMap
内联到重复的IO操作中,执行它的次数超过了必要的次数。 -fno-state-hack
禁用该优化并解决问题。解决问题的另一种方法是强制严格评估``mimeMap。
!mimeMap <- fmap M.fromList $ replicateM n [...]
但是,似乎还有一个regression in GHC 7.10,其中-fno-state-hack
无法解决问题。这就解释了为什么它没有为我解决。
非常感谢大家的回答。