繁体   English   中英

如何在不实际序列化的情况下估计Java中对象的序列化大小?

[英]How to estimate the serialization size of objects in Java without actually serializing them?

要增强群集中的消息传递,重要的是要在运行时了解消息的大小(我应该更喜欢处理本地消息还是远程消息)。

我可以找到基于java检测估计对象内存大小的框架。 我测试了classmexer,它没有接近序列化大小和sourceforge SizeOf。

在一个小的测试用例中,SizeOf错误大约10%,比序列化快10倍。 (仍然瞬态完全破坏了估计,因为例如ArrayList是瞬态的,但是被序列化为数组,修补SizeOf并不容易。但我可以忍受这种情况)

另一方面,10%的误差和10%的误差似乎不太好。 任何想法我怎么能做得更好?

更新:我还测试了ObjectSize( http://sourceforge.net/projects/objectsize-java )。 结果似乎只适合非继承对象:(

类在运行时获取的大小不一定与其在内存中的大小有关。 你提到的例子是瞬态场。 其他示例包括对象何时实现Externalizable并自行处理序列化。

如果一个对象实现Externalizable或提供readObject() / writeObject()那么最好的办法是将对象序列化到内存缓冲区以找出大小。 它不会很快,但它会准确。

如果对象使用默认序列化,则可以修改SizeOf以考虑瞬态字段。

序列化许多相同类型的对象后,您可以为该类型构建“序列化配置文件”,将序列化大小与SizeOf的运行时大小相关联。 这样您就可以快速估计序列化大小(使用SizeOf),然后将其与运行时大小相关联,以获得比SizeOf提供的结果更准确的结果。

其他答案中有许多好处,缺少的一点是序列化机制可能会缓存某些对象

例如,您序列化一系列对象A,B和C,这些对象在每个对象中包含两个对象o1和o2。 让我们说对象开销是100个字节,让我们说对象看起来像:

Object shared = new Object();
Object shread2 = new Object();

A.o1 = new Object()
A.o2 = shared


B.o1 = shared2
B.o2 = shared


C.o1 = shared2
C.o2 = shared

为简单起见,我们可以说通用对象需要50个字节来串行化,A的序列化大小为100(开销)+ 50(o1)+ 50(o2)= 200个字节。 人们也可以对B和C做出类似的天真估计。 但是,如果在调用reset之前所有三个都被相同的对象输出流序列化,那么你将在流中看到的是A和o1和o2的序列化,然后是b的序列化和o的b, 但是因为它引用了o2是已经序列化的同一个对象 所以假设一个对象引用需要16个字节,B的大小现在是100(开销)+ 50(o1)+ 16(o2的参考)= 166.所以序列化所需的大小现在已经改变了! 我们可以对C进行同步计算,并且缓存两个对象得到132个字节,因此所有三个对象的序列化大小不同,最大和最小之间的差异为~33%。

因此,除非每次难以准确估计序列化对象所需的大小时序列化整个对象而没有缓存。

只是一个想法 - 您可以首先将对象序列化为字节缓冲区,获取其长度并立即决定是将缓冲区内容发送到远程位置还是进行本地处理(如果它取决于消息大小)。

缺点 - 如果稍后决定不使用缓冲区,您可能会浪费时间进行序列化。 但是如果你估计你需要序列化就浪费估计工作量(因为在这种情况下你首先估计并在第二步中序列化)。

无法以精确的速度和速度来估计对象的序列化大小。 例如,一些对象可以是Pi数字的缓存,它们在运行时仅根据您需要的长度构造自身。 因此,它将仅序列化'length'属性的4个字节,而对象可能使用数百兆字节的内存来存储该Pi数。

我能想到的唯一解决方案是添加自己的接口,使用方法int estimateSerializeSize() 对于实现此接口的每个对象,您需要调用此方法以获得正确的大小。 如果某些Object没有实现它 - 您将不得不使用SizeOf。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM