我寫在Haskell一些簡單的字符計數程序,存儲統計在新的數據類型:優化哈斯克爾文本處理
data Stat = Stat {
stChars :: !Int,
stVowels :: !Int,
stPairEL :: !Int,
stWords :: !Int
}
我跑這了成百上千的純文本文件,每個約50K-100K。
tabulateFile :: FilePath -> IO Stat
tabulateFile path = do
putStrLn path
contents <- L.readFile path
return $! tabulateText ' ' contents defaultStat
而不是使用摺疊,我使用原始遞歸,所以我可以保留前一個字符。
tabulateText :: Char -> L.ByteString -> Stat -> Stat
tabulateText lastChr bs stat =
case U.uncons bs of
Nothing -> stat
Just (chr, newBs) ->
tabulateText lchr newBs (countChar lastChr lchr stat)
where lchr = toLower chr
{-# INLINE countChar #-}
countChar :: Char -> Char -> Stat -> Stat
countChar !lastChr !chr !(Stat stChars stVowels stPairEL stWords) =
Stat
(stChars + 1)
(stVowels + (countIf $ isVowel chr))
(stPairEL + (countIf (lastChr == 'e' && chr == 'l')))
(stWords + (countIf ((not $ isLetter lastChr) && isLetter chr)))
isVowel :: Char -> Bool
isVowel c = Set.member c vowels
vowels = Set.fromAscList ['a', 'e', 'i', 'o', 'u', ...] -- rest of vowels elided
現在,它更是作爲運行cat * | wc
的兩倍慢,但我的直覺告訴我,該文件I/O應足以抵消由佳緣需要的CPU時間。使用熱緩存只需使用cat * | wc
進程約20MB/s,但使用我的Haskell程序(編譯爲-O
)的運行速度低於10MB/s,即使經過一些基本的優化。剖析告訴我大部分時間都花在tabulateText
和countChar
之間。
有什麼我錯過了,我可以在這裏優化?
編輯:完整的文件粘貼到http://hpaste.org/74638
你可以發佈完整的文件到一些hpaste並在這裏發佈鏈接。它包含許多缺失的函數,我不想實現這些以便能夠運行您的代碼。 – Satvik
是的,對不起,我沒有早點知道。我已將鏈接添加到問題的結尾。 – erjiang