为了训练,我写了一个短小的Haskell程序来替代Perl脚本。该程序读取一个包含多行消息的日志文件,并将它们连接起来以产生每个消息一行的输出。我的测试输入文件有14000行,大小为1MB。使用Data.Text编写的版本运行时间为3.5秒,而使用Data.Text.Lazy编写的版本只需0.1秒(原始的perl脚本需要0.2秒)。我在其他帖子中发现,只有在处理大量数据时使用Data.Text.Lazy才有意义,我并没有期望会有这样的巨大差异。有人能解释一下原因或找出我的程序哪里出错了吗?
源代码的相关部分(两个版本之间唯一的区别是import Data.Text*):
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Char (isDigit)
import Data.Monoid ((<>))
import qualified Data.Text.Lazy as T
import qualified Data.Text.Lazy.IO as T
import System.Environment (getArgs, getProgName)
import System.IO (openFile, stdin, stdout, Handle,
IOMode(ReadMode,WriteMode))
main :: IO ()
main = do
(inp,out) <- getInput
actLog <- T.hGetContents inp
let newLog = processLog actLog
T.hPutStr out newLog
processLog :: T.Text -> T.Text
processLog = foldr joinLines "" . T.lines
joinLines :: T.Text -> T.Text -> T.Text
joinLines elem accu
| T.length elem == 0 = accu -- Blank Line
| T.head elem == ' ' = textElem <> accu -- Continuation
| isDigit (T.head elem) = "\n" <> textElem <> accu -- Start
| otherwise = accu -- Garbage
where textElem = T.strip elem
conduit
或pipes
的案例。 - AlecgetInput
标识符不在作用域内,它是否在程序的其他地方定义或从其他地方导入? - Michael Snoyman