Java:多线程字符流解码

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (15)

我正在维护一个高性能的CSV解析器,并尝试充分利用最新技术来提高吞吐量。对于这个特殊的任务来说,

  • 闪存(我们拥有相对便宜的PCI-Express卡,1 TB存储量,达到1 GB / s的持续读取性能)
  • 多核心(我们拥有一个便宜的Nehalem服务器,有16个硬件线程)

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

第二个实现使用一个线程来读取文件(在字节级),一个线程来解码字符(从ByteBuffer到CharBuffer)和多个线程来解析字段(我的意思是将分隔的文本字段解析为双打,整数,日期...)。这工作速度更快,我们的盒子上接近400MB /秒。

但仍远低于我们的存储性能。而且这些固态硬盘将在未来再次改善,我们并没有从Java中获得最大收益。很显然,当前的限制是字符解码(CharsetDecoder.read(...))。这是瓶颈,在强大的Nehalem处理器上,它以400MB / s的速度将字节转换为字符,相当不错,但这必须是单线程的。CharsetDecoder有些有状态,取决于使用的字符集,并且不支持多线程解码。

所以我对社区的问题是(并感谢您阅读这篇文章到目前为止):有谁知道如何并行Java中的字符集解码操作?

提问于
用户回答回答于

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

你怎么知道?请问您的监视/分析显示确凿解码器线程使用的核心之一的100%?

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

如果UTF-8解码无疑是瓶颈,那么应该可以并行执行任务。但是你肯定需要实现你自己的解码器来做到这一点。

用户回答回答于

有谁知道如何并行Java中的字符集解码操作?

你可能能够打开多个输入流来做到这一点(我不确定你将如何使用NIO去做这件事,但它一定是可能的)。

这将取决于您解码的编码的难度。您将需要针对目标编码的定制解决方案。如果编码具有固定的宽度(例如Windows-1252),那么一个字节==一个字符和解码很容易。

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

一些传统的可变宽度编码可能不是这样精心设计的,所以您将别无选择,只能从数据的开始进行解码并顺序读取。

如果它是一个选项,请将您的数据生成为UTF-16BE。然后你可以切出解码并直接读取两个字节到一个字符。

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

扫码关注云+社区