首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java:多线程字符流解码

Java:多线程字符流解码
EN

Stack Overflow用户
提问于 2010-08-09 16:39:11
回答 4查看 1.2K关注 0票数 18

我正在维护一个高性能的CSV解析器,并试图最大限度地利用最新技术来提高吞吐量。对于此特定任务,这意味着:

Nehalem闪存(我们拥有相对便宜的PCIExpress卡,1 TB的存储,可达到1 GB/s的持续读取performance)

  • Multiple核心)(我们拥有一台具有16个硬件线程的廉价
  • 服务器)

CSV解析器的第一个实现是单线程的。文件读取,字符解码,字段分割,文本解析,所有这些都在同一个线程中。其结果是吞吐量约为50MB/s。不错,但远低于存储限制……

第二个实现使用一个线程读取文件(在字节级别),一个线程解码字符(从ByteBuffer到CharBuffer),使用多个线程解析字段(我指的是将分隔的文本字段解析为双精度、整数、日期...)。这个速度更快,在我们的机器上接近400MB/s。

但仍远低于我们的存储性能。这些SSD在未来会再次改善,我们不会在Java中发挥最大的作用。很明显,当前的限制是字符解码( CharsetDecoder.read(...) )。这就是瓶颈,在功能强大的Nehalem处理器上,它以400MB/s的速度将字节转换为字符,非常好,但这必须是单线程的。CharsetDecoder是有状态的,这取决于所使用的字符集,并且不支持多线程解码。

所以我向社区提出的问题是(感谢你到目前为止阅读了这篇文章):有人知道如何在Java中并行化字符集解码操作吗?

EN

回答 4

Stack Overflow用户

发布于 2010-08-09 18:00:19

有人知道如何在

中并行化字符集解码操作吗?

您可以打开多个输入流来完成此操作(我不确定如何使用NIO完成此操作,但这必须是可能的)。

这会有多难,取决于你解码的编码。对于目标编码,您需要一个定制的解决方案。如果编码有一个固定的宽度(例如Windows1252),那么一个字节==一个字符和解码是很容易的。

现代的可变宽度编码(如UTF-8和UTF-16)包含用于标识字符序列的第一个字节的规则,因此可以跳到文件的中间并开始解码(您必须注意上一个块的结尾,因此首先开始解码文件的结尾是明智的做法)。

一些传统的可变宽度编码可能没有这么好的设计,因此您将别无选择,只能从数据的开头解码并按顺序读取它。

如果可以,则将数据生成为UTF-16BE格式。然后你就可以省去解码,直接把两个字节读成一个字符。

如果文件是Unicode,请注意BOM处理,但我猜您已经熟悉了许多低级细节。

票数 4
EN

Stack Overflow用户

发布于 2010-08-09 18:03:49

很明显,当前的限制是字符解码( CharsetDecoder.read(...) )

你怎么知道的?您的监控/分析是否最终显示解码器线程正在使用您的某个核心的100%?

另一种可能性是操作系统无法以其理论上的最大速度驱动SSD。

如果UTF-8解码肯定是瓶颈,那么应该可以并行完成这项任务。但您肯定需要实现自己的解码器才能做到这一点。

票数 1
EN

Stack Overflow用户

发布于 2010-08-11 17:56:28

另一种(疯狂的)替代方案是将输入分成任意大小的块,忽略解码问题,然后并行解码每个块。但是,您希望确保块重叠(具有参数化的大小)。如果两个线程以相同的方式解码两个块的重叠区域(并且您的重叠对于指定的编码来说足够大),那么连接结果应该是安全的。重叠越大,需要的处理就越多,出错的概率就越小。此外,如果您知道编码是UTF-8或类似的简单编码,则可以将重叠设置得非常低(对于该客户端),并且仍然可以保证正确的操作。

如果第二个块被证明是错误的,你将不得不重做,所以不要并行处理大块是很重要的。如果并行执行两个以上的块,从头到尾进行“修复”将很重要,这样一个未对齐的块就不会导致下一个块(可能正确对齐)无效。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3438466

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档