我什么时候使用ByteString,什么时候不使用?

Tim*_*rry 24 io performance haskell bytestring

我对SPOJ上的PRIME1问题的尝试一直很糟糕.我发现使用ByteString 实际上有助于在问题文本中阅读的性能.但是,使用ByteString写出结果实际上比使用Prelude函数稍慢.我想知道我做错了,或者这是否是预期的.

我使用(putStrLn.show)和ByteString等效三种不同的方式进行了分析和计时:

  1. 我测试每个候选人,看它是否是素数.如果是这样,我将它添加到列表并用(putStrLn.show)写出来
  2. 我列出了所有素数并使用(putStrLn.unlines.show)写出列表
  3. 我列出所有素数并使用map(putStrLn.show)写出列表

我期望数字2和3执行速度较慢,因为您在一个函数中构建列表并在另一个函数中使用它.通过在生成数字时打印数字,我避免为列表分配任何内存.另一方面,每次调用putStrLn时都要进行一次调用系统调用.对?所以我测试了,#1实际上是最快的.

使用选项#1和Prelude([Char])函数实现了最佳性能.我期望我的最佳表现是ByteString的选项#1,但事实并非如此.我只使用懒惰的ByteStrings,但我认为这不重要.是吗?

一些问题:

  • 你是否希望ByteStrings能够更好地将一堆Integer写入stdout?
  • 我错过了一种方式模式来生成并写出可以带来更好性能的答案吗?
  • 如果我只是将数字写为文本,那么,如果有的话,使用ByteString有什么好处?

我的工作假设是,如果你没有将它们与其他文本组合,用ByteString写出Integer是比较慢的.如果您将Integers与[Char]结合使用,那么使用ByteStrings可以获得更好的性能.即,ByteString重写:

putStrLn $ "the answer is: " ++ (show value)
Run Code Online (Sandbox Code Playgroud)

将比上面写的版本快得多.这是真的?

谢谢阅读!

Don*_*art 21

使用字节串进行批量输入通常更快,因为数据密集,从磁盘到内存的数据更少.

然而,将数据写为输出则略有不同.通常,您要序列化结构,生成许多小写入.因此,在这种情况下,字节串的密集,批量写入对您没有多大帮助.即使是常规Strings也会合理地增加产量.

但是,一切都不会丢失.我们可以通过在内存中有效地构建字节串来恢复快速批量写入.这种方法由各种*-builder包采用:

我们不是将值转换为许多微小的字节串,而是一次一个地写出来,而是将转换流转换为不断增长的缓冲区,然后将缓冲区写入一个大块.与字符串IO相比,这会导致更少的IO开销和性能改进(通常是显着的).

这种方法是采取在Haskell例如Web服务器,或者有效的HTML系统,杀出.

此外,即使使用批量写入,性能也取决于类型和字节串之间的任何转换函数的效率.因为Integer,您可能只是将内存中的位模式复制到输出,或者通过一些低效的解码器.因此,您有时需要考虑一下您正在使用的编码函数的质量,而不仅仅是使用Char/String还是bytestring IO.


tib*_*bbe 7

请注意,性能不是ByteString和之间的主要区别String.前者用于二进制数据,后者用于Unicode文本.如果您有二进制数据,请使用ByteString,如果您有Unicode文本,请使用文本包中Text类型.