我正在编写一个需要从单个文件快速反序列化数百万条消息的应用程序。
应用程序要做的实际上是从文件中获取一条消息,做一些工作,然后丢弃该消息。每条消息都由约100个字段组成(并非总是解析所有字段,但我需要全部这些字段,因为应用程序的用户可以决定他要处理的字段)。
此时,应用程序包含一个循环,该循环在每次迭代中仅使用readDelimitedFrom()
调用执行。
有没有一种方法可以优化问题以更好地适应这种情况(拆分为多个文件等)。此外,由于邮件数量和每封邮件的尺寸,此刻,我需要对文件进行gzip压缩(由于字段的值非常重复,因此可以有效地减小文件大小)-尽管这会减少性能。
如果CPU时间是您的瓶颈(如果直接从具有冷缓存的HDD加载是不太可能的,但是在其他情况下可能是这种情况),那么可以通过以下几种方法来提高吞吐量:
如果可能,请使用C ++而不是Java,并在循环的每次迭代中重用相同的消息对象。这减少了在内存管理上花费的时间,因为每次都会重复使用相同的内存。
而不是使用readDelimitedFrom()
,而是构造一个CodedInputStream
并使用它来读取多个消息,如下所示:
// Do this once:
CodedInputStream cis = CodedInputStream.newInstance(input);
// Then read each message like so:
int limit = cis.pushLimit(cis.readRawVarint32());
builder.mergeFrom(cis);
cis.popLimit(limit);
cis.resetSizeCounter();
(一种类似的方法在C ++中起作用。)
使用Snappy或LZ4压缩而不是gzip。这些算法仍可获得合理的压缩率,但针对速度进行了优化。(尽管Snappy是Google考虑到Protobufs开发的,但LZ4可能更好一些,因此您可能要在数据集上对它们进行测试。)
考虑使用Cap'n Proto而非协议缓冲区。不幸的是,还没有Java版本,但是编辑:有capnproto-java以及许多其他语言的实现。在它支持的语言中,已经证明它要快得多。(公开:我是Cap'n Proto的作者。我还是Protocol Buffers v2(这是Google发布的开源版本)的作者。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句