2009-03-02 49 views
5

我必須將大型對象樹(7,000)序列化到磁盤中。最初我們將這棵樹與Kodo一起保存在一個數據庫中,但是它會讓成千上萬的查詢將這棵樹加載到內存中,並且它將佔用本地宇宙可用時間的很大一部分。Java對象序列化性能提示

我試過這個序列化,事實上我得到了一個性能改進。但是,我感覺我可以通過編寫自己的自定義序列化代碼來改善這一點。我需要儘可能快地加載這個序列化的對象。

在我的機器上,序列化/反序列化這些對象大約需要15秒。從數據庫加載它們時,大約需要40秒。

關於我能做些什麼來改善這種性能的任何提示,考慮到因爲對象在樹中,它們互相引用?

回答

6

一個優化是自定義類描述符,以便將類描述符存儲在不同的數據庫中,並將對象流存儲在只通過ID引用它們的對象流中。這減少了序列化數據所需的空間。例如,請參閱類別SerialUtilClassesTable在一個項目中的做法。

使類Externalizable而不是Serializable可以提供一些性能優勢。缺點是它需要大量的手動工作。

然後還有其他序列化庫,例如jserial,它可以提供比Java默認序列化更好的性能。另外,如果對象圖不包含週期,那麼它可以序列化得更快一點,因爲序列化器不需要跟蹤它所看到的對象(參見jserial's FAQ中的「它是如何工作的?」)。

1

你試過壓縮流(GZIPOutputStream)嗎?

+0

我需要改進加載和存儲性能,但我沒有在問題中指定,而且空間也是一個「性能」度量。 – 2009-03-02 12:19:48

+0

只有當序列化過程是磁盤綁定時,空間越少意味着磁盤訪問次數越少意味着時間越少 – 2009-03-02 22:12:13

+0

。它似乎不在我的系統上;它似乎是cpu-bound,所以壓縮只會進一步減慢它的速度。 – 2009-11-21 07:42:02

1

這是我會怎麼做,構成了我的頭頂

系列化

  1. 序列化每個對象單獨
  2. 爲每個對象分配一個唯一的密鑰
  3. 當一個對象持有引用另一個對象,將該對象的唯一鍵放入序列化中的對象位置。 (我將使用轉換爲二進制一個UUID)
  4. 保存每個對象到一個文件/數據庫/存儲使用所述固有密鑰

反序列化

  1. 開始形成任意對象(通常是根我嫌疑人)將其反序列化並將其映射到映射中,並將其作爲唯一鍵作爲索引並返回
  2. 當您在序列化流中登錄對象鍵時,首先檢查它是否已被解序列化,方法是查看它的唯一鍵地圖和如果它只是從那裏抓住它,如果沒有放置一個懶惰的加載代理(它重複這個對象的這兩個步驟),而不是真正的對象,當你需要它時,鉤子會加載正確的對象。

編輯,您可能需要使用雙通道序列化和反序列化,如果你有在那裏循環引用,有點複雜的事情 - 但不是那麼多。

+0

這可能會起作用,但需要重新處理相當一部分代碼 – 2009-03-02 12:19:16

+0

這對標準序列化有何改進?據我所知,這已經由默認機制完成了。 – 2009-03-02 12:25:43

+0

@saua因爲您可以在需要時懶惰地加載和實例化每個對象,而不是一次加載所有對象,您也可以自己下載字節級別並優化序列化格式。 – thr 2009-03-02 12:30:03

0

爲了提高性能,我建議不要使用java.io序列化。相反,你可以自己下載字節。

如果您打算使用java.io serialise樹,您可能需要確保遞歸不會太深,可以通過展平(比如說TreeSet)或者先安排序列化最深的節點(所以你有回參考,而不是嵌套readObject調用)。

如果科多沒有辦法在一個(或幾個)閱讀整棵樹,我會感到驚訝。

10

不要忘記對不需要序列化的實例變量使用'transient'關鍵字。這可以提高性能,因爲您不再讀取/寫入不必要的數據。

4

我會推薦你​​實現自定義writeObject()readObject()方法。 通過這種方式,您將能夠爲樹中的每個節點分配文字chidren節點。當你使用默認序列化時,每個節點都將被序列化爲它的所有子節點。

例如,的writeObject()一個類應通過一個樹的所有節點迭代和只寫節點的數據(沒有節點本身)用一些標記,其識別樹水平的

你可以看看LinkedList,看看這些方法是如何實現的。它使用相同的方法來防止爲每個單個條目寫入prev和next條目。

4

爲了避免必須編寫自己的序列化代碼,請嘗試使用Google Protocol Buffers。根據他們的網站:

協議緩衝區是谷歌的語言中立,平臺中立,可擴展的機制序列化結構化數據 - 認爲XML,但更小,更快,更簡單。您可以定義一次數據的結構,然後您可以使用特殊的源代碼輕鬆地將結構化數據寫入和讀取各種數據流以及使用各種語言 - Java,C++或Python

我沒有用過它,但聽說過很多積極的事情。另外,我必須保留一些自定義的序列化代碼,這可以是一個絕對的噩夢(更別提跟蹤bug了),所以讓其他人爲你做這件事總是一件好事。

0

此外,看看XStream,一個庫,將對象序列化爲XML並再次返回。

0

您可以使用Colfer來生成bean,Java的標準序列化性能將得到10 - 1000倍的提升。除非尺寸超過GB,否則你會低於一秒。