簡體   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