16 java multithreading character-encoding
我正在维护一个高性能的CSV解析器,并尝试充分利用最新技术来提高吞吐量.对于此特定任务,这意味着:
CSV解析器的第一个实现是单线程.文件读取,字符解码,字段拆分,文本解析,都在同一个线程中.结果是吞吐量约为50MB/s.不错但远低于存储限制......
第二个实现使用一个线程来读取文件(在字节级别),一个线程来解码字符(从ByteBuffer到CharBuffer),以及多个线程来解析字段(我的意思是将分隔的文本字段解析为双精度,整数,日期...).这种方法运行得更快,在我们的盒子上接近400MB/s.
但仍远低于我们的存储性能.而且这些SSD将来会再次改进,我们并没有在Java中充分利用它.很明显,当前的限制是字符解码(CharsetDecoder.read(...)).这是瓶颈,在强大的Nehalem处理器上,它将字节转换为400MB/s的字符,非常好,但这必须是单线程的.CharsetDecoder在某种程度上是有状态的,具体取决于使用的字符集,并且不支持多线程解码.
所以我对社区的问题是(并且感谢您阅读目前为止的帖子):有没有人知道如何在Java中并行化charset解码操作?
有谁知道如何在Java中并行化字符集解码操作?
您也许可以打开多个输入流来执行此操作(我不确定您将如何使用 NIO 进行此操作,但它一定是可能的)。
这有多困难取决于您解码的编码。您将需要针对目标编码的定制解决方案。如果编码具有固定宽度(例如Windows-1252),则一个字节==一个字符并且解码很容易。
现代可变宽度编码(如 UTF-8 和 UTF-16)包含用于识别字符序列第一个字节的规则,因此可以跳转到文件的中间并开始解码(您必须注意前一个块的末尾,因此明智的做法是首先开始解码文件的末尾)。
一些传统的可变宽度编码可能没有设计得这么好,因此您别无选择,只能从数据的开头进行解码并按顺序读取它。
如果可以选择,请将数据生成为 UTF-16BE。然后您可以删除解码并将两个字节直接读取为字符。
如果文件是 Unicode,请注意 BOM 处理,但我猜您已经熟悉许多低级细节。