Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 如何提高在Haskell中为输出生成字符串的性能_Performance_Haskell - Fatal编程技术网

Performance 如何提高在Haskell中为输出生成字符串的性能

Performance 如何提高在Haskell中为输出生成字符串的性能,performance,haskell,Performance,Haskell,我有一个计划,我正试图使更快,主要是为了使它更快地了解更多关于哈斯克尔。为了比较,我用C编写了相同的程序,速度提高了4倍。我希望C能更快,但这种差异让我觉得我做错了什么 因此,我分析了Haskell代码,超过50%的时间用于生成格式化的字符串,以供输出。所以这一部分比我的整个C程序要花更多的时间。该功能与此类似: display :: POSIXTime -> [(Int, Centi)] -> IO() display t l = putStrLn $ t_str ++ " " +

我有一个计划,我正试图使更快,主要是为了使它更快地了解更多关于哈斯克尔。为了比较,我用C编写了相同的程序,速度提高了4倍。我希望C能更快,但这种差异让我觉得我做错了什么

因此,我分析了Haskell代码,超过50%的时间用于生成格式化的
字符串
,以供输出。所以这一部分比我的整个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
关于代码的注释:
unsafeccoerce
是将
NominalDiffTime
转换为具有相同类型的
DiffTime
,但这比
torional更快。我一直在使用的fromRational

Centi
是在
数据中定义的。固定的
是一个小数点后两位的数字

TimeOfDay
与您预期的一样,只有小时、分钟和秒(以皮秒精度存储)

`mod`posixDayLength
就是这样,我们只需要得到一天中的时间,而忽略它是哪一天(因为这就是我所关心的……它来自一个时间戳,我知道它必须是今天——我只关心今天几点!)

我曾尝试使用
显示(字符串->字符串)
来连接结果,但速度并没有明显加快

我曾尝试使用
Data.Text
,但这会使代码速度变慢(可能会花费太多时间打包字符串)

我曾经将
putStrLn
放在一个单独的函数中,但在这里速度更快(生成的thunks更少?但为什么?)


有没有一种简单的方法可以提高Haskell中我所缺少的输出性能?

对于生成输出,可以通过避免使用字符串而使用ByteString或Text来获得最高性能。为了生成输出,有一种称为
Builder
的特殊数据类型。[ByteString]hackage描述中有一个很好的示例描述

生成的代码如下所示:

import Data.Monoid
display :: POSIXTime -> [(Int, Centi)] -> IO()
display t l = hPutBuilder stdout $ t_str <> space <> l_str
    where
        space = (byteString . pack) " "
        t_str = (byteString . pack . show . timeToTimeOfDay . unsafeCoerce) $ (t `mod` posixDayLength)
        l_str = foldr <> space $ map displayPair l
        displayPair (a,b) = intDec a <> space <> (byteString . pack . show) b
导入数据.Monoid
显示::POSIXTime->[(整数,厘米)]->IO()
显示TL=hPutBuilder标准输出$t\U str空间l\U str
哪里
空格=(byteString.pack)”
t_str=(byteString.pack.show.timeToTimeOfDay.unsafectorce)$(t`mod`posixDayLength)
l_str=foldr space$map displayPair l
displayPair(a,b)=intDec a空间(byteString.pack.show)b

构建器数据类型构建块,然后在O(1)中将其连接到输出的缓冲区中。不幸的是,并非所有类型都有生成器,只有基类型有生成器。因此,对于输出其他字符串,唯一的解决方案是打包字符串。。。或者编写一个函数来创建生成器(并将其添加到库中?)

type String=[Char]
不适用于(也不适用于)性能重要的任何情况。(
Data.ByteString
Data.Text
是。)但这有关系吗?这可能受到IO性能的限制,我认为C版本在程序本身几乎没有执行时间。尝试使用
Text
而不是
String
!链表不是为了性能。但是putStrLn的类型是::String->IO。那么,我如何避免IO中的字符串呢?@dave Use如果您发布编译并使用
Criteria
TimeIt
的完整代码,我愿意帮助您。您可以使用
OverloadedStrings
扩展来避免构造(然后立即丢弃)任何字符串文本。您可以使用Data.Text.Builder来编写生成器,而不是使用
show
来显示值(毕竟这是它的预期用途)。我不认为不完美的强制是必要的,我建议避免它。@ReinHenrichs:看看它为什么存在的问题:有必要将
NominalDiffTime
转换为
DiffTime
,两者都有相同的表示,并且比备选
(fromRational.torional)
更快