我有一个程序,我试图让它运行更快,主要是为了学习更多关于Haskell的知识。作为比较,我已经用C写了同样的程序,并获得了4倍的速度提升。我预期C会更快,但这种差异让我认为我做错了什么。
因此,我对Haskell代码进行了分析,发现超过50%的时间花费在生成格式化的
关于代码的注释:
我尝试过使用
我尝试过使用
我曾经把
有没有简单的方法可以改进Haskell的输出性能?我有所遗漏吗?
因此,我对Haskell代码进行了分析,发现超过50%的时间花费在生成格式化的
String
上。所以仅这一部分就比我的整个C程序运行时间还要长。这个函数类似于以下形式:display :: POSIXTime -> [(Int, Centi)] -> IO()
display t l = putStrLn $ t_str ++ " " ++ l_str
where
t_str = show . timeToTimeOfDay . unsafeCoerce $ (t `mod` posixDayLength)
l_str = intercalate " " $ map displayPair l
displayPair (a,b) = show a ++ " " ++ show b
关于代码的注释:
unsafeCoerce
是将NominalDiffTime
转换为DiffTime
,它们具有相同的类型,但这比我之前使用的toRational . fromRational
更快。
Centi
在Data.Fixed
中定义,是一个带有2位小数的数字。
TimeOfDay
只包含小时、分钟和秒(以皮秒精度存储)。
`mod` posixDayLength
是为了忽略日期,仅获取当天的时间(因为这是我关心的...从时间戳得到,并且我知道它必须是今天 - 我只关心今天的时间)。我尝试过使用
ShowS(String -> String)
来连接结果,但这并不明显更快。我尝试过使用
Data.Text
,但这使得代码变慢了(可能是花费了太多时间打包字符串)。我曾经把
putStrLn
放在一个单独的函数中,但在这里它更快(少建立thunk?但是为什么?)。有没有简单的方法可以改进Haskell的输出性能?我有所遗漏吗?
type String = [Char]
并不适合(也不是设计用来)处理对性能要求较高的任务(Data.ByteString
和Data.Text
则更为适用)。但这是否重要呢?我认为这很可能受到IO性能的限制,C版本几乎没有在程序本身中执行任何时间。 - leftaroundabout++
- 使用 Text 的append
会更快。 - Thomas M. DuBuisson