5

I have a Java program which prepares data into a fairly complex and big data structure in memory (several GB) and serializes it to disk, and another program which reads back the serialized data structure in memory. I was surprised to notice that the deserialization step is pretty slow, and that it is CPU-bound. (100% CPU usage in top but only 3 to 5 MB/s read with iotop, which is very low for what should be sequential reads on a hard drive). The CPU is fairly recent (Core i7-3820), the structure fits in memory, no swap space is configured.

Why is this so? Is there an alternative way to serialize objects in Java which does not have the CPU as bottleneck?

Here is the deserialization code, in case it matters:

FileInputStream f = new FileInputStream(path);
ObjectInputStream of = new ObjectInputStream(f);
Object obj = of.readObject();
4

2 回答 2

4

反序列化非常昂贵。如果您使用通用反序列化,它将使用大量反射和创建对象。

有很多更快的替代方案,并且大多数使用生成的代码而不是反射。

http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

您会注意到最快的方法之一是使用 Externalizable,这可能是您的一个选择。这意味着为对象的序列化和反序列化添加自定义方法。

我已经编写了最快的方法,但这避免了通过回收它们或就地使用文件中的数据来创建任何对象(即不需要反序列化它们)

于 2012-04-10T15:34:55.907 回答
2

如果不使用分析器查看此内容或对对象结构的实际层次结构了解很多,很难说,但我假设如果它“相当复杂”并且大约为“几 GB”,那么你可能处理数以千计的单个对象。

我最好的猜测是你的性能被 Java 反射杀死了。反射用于从您的流中构造对象,已知它比直接在代码中调用构造函数慢至少两个数量级。因此,如果您的对象有大量“小”对象,反射将花费大量时间来重建它们。

您可以尝试的一件事(如果您还没有尝试的话)是在每个类的顶部声明以下行Serializable

private static final long serialVersionUID = [some number]L;

如果您不声明此 ID,Java 将不得不计算它,因此您通过声明它确实节省了一些 CPU 周期。

供进一步参考:

http://oreilly.com/catalog/javarmi/chapter/ch10.html

于 2012-04-10T15:35:50.740 回答