Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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:Data.Text与Data.Text.Lazy性能_Performance_Haskell - Fatal编程技术网

Performance Haskell:Data.Text与Data.Text.Lazy性能

Performance Haskell:Data.Text与Data.Text.Lazy性能,performance,haskell,Performance,Haskell,为了进行培训,我编写了一个简短的Haskell程序来替代Perl脚本。 该程序读取一个包含多行消息的日志文件,并简单地将它们连接起来,以便为每条消息生成一行。 我的测试输入文件有14000行,大小为1MB。 使用Data.Text的版本的运行时间为3.5秒,使用Data.Text.Lazy的版本仅为0.1秒(原始perl脚本需要0.2秒)。 我在其他帖子中发现,使用Data.Text.Lazy只对非常大量的数据有意义,并没有想到会有如此大的差异。 有人能解释一下我的程序有什么问题吗 源的相关部分

为了进行培训,我编写了一个简短的Haskell程序来替代Perl脚本。 该程序读取一个包含多行消息的日志文件,并简单地将它们连接起来,以便为每条消息生成一行。 我的测试输入文件有14000行,大小为1MB。 使用Data.Text的版本的运行时间为3.5秒,使用Data.Text.Lazy的版本仅为0.1秒(原始perl脚本需要0.2秒)。 我在其他帖子中发现,使用Data.Text.Lazy只对非常大量的数据有意义,并没有想到会有如此大的差异。 有人能解释一下我的程序有什么问题吗

源的相关部分(两个版本之间的唯一区别是导入数据。Text*):

{-#语言重载字符串}
模块主要在哪里
导入数据.Char(isDigit)
导入数据。Monoid(())
将限定的Data.Text.Lazy作为T导入
将限定的Data.Text.Lazy.IO作为T导入
导入System.Environment(getArgs、getProgName)
导入System.IO(openFile、标准输入、标准输出、句柄、,
IOMode(读模式、写模式))
main::IO()
main=do
(输入,输出)T.文本->T.文本
累积线
|T.长度元素==0=accu--空行
|T.head elem==''=textElem accu——续
|isDigit(T.head元素)=“\n”text元素累计——开始
|否则=accu--垃圾
其中textElem=T.strip elem

惰性数据和普通数据之间的区别。文本是整个文件是否同时读入内存

actLog <- T.hGetContents inp 

actLog这看起来像是数据结构问题,而不是惰性问题。严格的
文本
本质上是一大块内存,而懒惰的
文本
本质上是严格的
文本
的链接列表(“块”)。懒散的
文本
被分割成块的方式不应该是值含义的一部分(它只是通过连接所有块获得的文本)。但这会对运营成本产生很大影响

您有一系列
short accu
形式的操作,其中
accu
随着输出的大小而增长。如果这些是严格的
文本
s,则此串联必须将
short
accu
的全部内容复制到新的严格的
文本
值中。总运行时间必然是二次的。如果它们是惰性的
文本
s,那么
还有另一个选项:它可以将
短的块列表预先添加到
accu
的块列表中。这根本不需要触碰
accu
,但即使触碰了,组成
accu
的区块链表的脊椎可能比
accu
的整个文本内容要少得多,具体取决于区块大小。这就是为什么你的懒
文本
版本要快得多

看起来你可以用下面的格式编写你的程序

processLog = T.unlines . processLines . T.lines
processLines :: [T.Text] -> [T.Text]
processLines = ...

这就留下了如何连接到库函数
T.unlines
的问题,在这种情况下,不管您使用的是严格的
Text
还是懒惰的
Text

问题,这是一个要求使用
导管
管道
的用例。
getInput
标识符不在范围内,它是在程序的其他地方定义的还是从其他地方导入的?getInput是在其他地方定义的,根据命令行参数,它返回输入的stdin或打开的文件句柄,输出的stdout或文件句柄。我理解这一点,但在这两种情况下,程序都读取并处理完整的文件。我不认为在一个块中读取一个1MB的文件比逐行读取要花费35倍的时间,内存占用也要小得多。但我同意这只是解释了速度增加的一部分。通过将“let newLog=processLog actLog”更改为“newLog”newLog my bad忘记将其包装在monad中,您可以强制使用内存并消除一些懒散现象“newLog是的,这确实可以编译,但在重写程序后,运行时仍然相同,因为建议两个版本具有相同的运行时
processLog = T.unlines . processLines . T.lines
processLines :: [T.Text] -> [T.Text]
processLines = ...