Java:多线程字符流解码
我正在维护一个高性能的CSV解析器,并试图充分利用最新技术来提高吞吐量。对于此特定任务,这意味着:Java:多线程字符流解码,java,multithreading,character-encoding,Java,Multithreading,Character Encoding,我正在维护一个高性能的CSV解析器,并试图充分利用最新技术来提高吞吐量。对于此特定任务,这意味着: 闪存(我们拥有一个相对便宜的PCI Express卡,1 TB的存储容量,可达到1 GB/s的持续读取性能) 多核(我们拥有一台廉价的Nehalem服务器,具有16个硬件线程) CSV解析器的第一个实现是单线程的。文件读取、字符解码、字段拆分、文本解析,都在同一个线程中。结果是吞吐量约为50MB/s。不错,但远低于存储限制 第二个实现使用一个线程读取文件(在字节级别),一个线程解码字符(从By
- 闪存(我们拥有一个相对便宜的PCI Express卡,1 TB的存储容量,可达到1 GB/s的持续读取性能)
- 多核(我们拥有一台廉价的Nehalem服务器,具有16个硬件线程)
如果UTF-8解码确实是瓶颈,那么应该可以并行完成任务。但是您肯定需要实现自己的解码器来实现这一点。如果您知道编码,并且编码是固定大小的,或者不包含重叠的字节序列,则可以扫描特殊序列。在CSV中,换行符序列可能有意义。即使您动态地检测编码,您也可以运行前几个字节的过程来确定编码,然后继续并行解码。另一个(疯狂的)替代方法是将输入分成任意大小的块,忽略解码问题,然后并行解码每个块。但是,您希望确保块重叠(具有参数化大小)。如果两个线程以相同的方式对两个块的重叠区域进行解码(并且您的重叠对于指定的编码来说足够大),那么合并结果应该是安全的。重叠越大,所需的处理越多,错误概率越小。此外,如果您知道编码是UTF-8或类似的简单编码,那么可以将重叠设置得很低(对于该客户机),并且仍然可以保证正确的操作
如果第二个块被证明是错误的,您将不得不重做它,因此重要的是不要并行处理大块。如果并行执行两个以上的块,则必须从头到尾“修复”,以便一个未对齐的块不会导致下一个块(可能已正确对齐)无效。不幸的是,UTF-16是一种可变长度编码。您需要UTF32来进行这种简单的Unicode解析。@ GRDDEV-我在我的文章中涵盖了这一点——在UTF -16数据流的中间可以识别字符序列。高代理对是0xD800—0xDbFF,低代理是0xDC00 -0xDFFF。其他任何内容都包含在一对字节中。我的评论提到了UTF-16BE。你不能完全停止解码。但这真的很简单。感谢那些鼓舞人心的元素。当然,固定长度编码相对容易并行化。可以将原始字节存储在块中,以确保块不会在中间剪切字符,在并发任务中解码块并组装结果。也许我应该这样做,当我检测到一个可变长度的字符集时,就回到单线程模式。当然,我的目标是提供一个CSV解析器,无论字符集是什么,它都可以工作,以向世界各地的客户提供它的外来字符集。可能可以为各种字符集解码器的后续产品(如sun.nio.cs.UTF_8.Decoder等)获取源代码