聽過 PHPRPC 嗎?試試我的 Hign!

來源:互聯網
上載者:User
·〉前言

在企業級應用程式中,常常需要將某個類(可能複雜、組合、等等)進行本地化。當然,個人感覺微軟所提供的 Binary 序列化是最“保險”的方式。可惜這是一個略有遺憾的序列化器。常見問題如程式集版本的問題(雖然有 Binder 可以解決),以及致命的序列化的效率和用時令人不敢恭維。而 XML 序列化僅僅適用於簡單對象的本地化。

無意之中,在網路中尋找到了PHPRPC。這是一個非常輕型,非常棒的序列化器。

PHPRPC,它的商業版本是Hprose。 PHPRPC 採用的序列化方式是 PHP 序列化。你可以認為它是一種半文字格式設定,因為文本和二進位位元組流的特徵它都具有。 比如表示數字時,它採用的是數位文字格式設定,而不是二進位的機器儲存格式,這樣它就可以在不同的平台上傳遞而無須擔心位元組序引起的解析問題。而它又像二進位位元組流那樣不允許在資料當中插入多餘的空白(空格、斷行符號、換行等字元),並且對於字串、數組、字典、對象還有長度描述資訊。這些特徵決定了它既有純文字格式的通用性,又具有二進位位元組流的快速解析能力。

PHPRPC For .NET 無論是效率,還是大小,都是非常棒的。如果讀者對 PHPRPC 還不是很瞭解,或者對他的效能表示懷疑,可以閱讀這篇文章(http://www.cnblogs.com/xlai/archive/2010/10/19/1855736.html),這篇文章詳細的測試 PHPRPC 和其他序列化器的效能。毋庸置疑,在沒有找到其他序列化器,這是一個非常好的選擇。據聞,PHPRPC 有一個商業版,效能和效率更勝一籌,可惜無緣嘗試。

但是,PHPRPC也不是全能的(至少 For .NET 是這樣的)。例如對於十分複雜的組合對象,PHPRPC的序列化是拋出異常的。更要命的是,對於object類型的解析,PHPRPC顯得過於2B了。例如對於List<object>、Dictionary<object,object>的處理更是一塌糊塗。雖然官方扯蛋的說:支援複雜物件傳輸的。

幸好,PHPRPC是一個開源的項目。翻開源碼後,有一種熱血立即湧上胸口!

——自己寫一個。

·〉PHPRPC的不足

PHPRP的思路是非常美妙的,比如對字串的長度描述,複雜物件的“Reference”特性等,在自己寫序列化器的過程中,PHPRPC的源碼令人受益匪淺。現在主要列舉幾個PHPRPC亟待解決的問題(可能不影響正常的使用),再一一列出解決方案。

1、對ICollection、IList和IDictionary的類型支援不夠,我想應當是PHPRPC為了縮短序列化後的大小,特意對這三個常用的類型進行特別處理,無奈的是,PHPRPC處理的方式並不是最佳的,比如前文所提到的“List<object>”,如果在“List<object>”中存有一個字串,那麼還原序列化,就會成了一個 byte[]數組。通過觀賞代碼,BUG是在【PHPReader檔案的private AssocArray ReadAssocArray(Stream stream, ArrayList objectContainer)函數】。

2、也正因為PHPRPC對IDictionary、ICollection、ILIst的特殊處理,導致了對於實現三個介面任意對象,不序列化其自訂屬性,而只序列化集合所包含的元素。

3、PHPRPC並不支援多維陣列。如果你的維數大於1,那麼就會拋出【throw new RankException("Only single dimension arrays are supported here.")】的異常。雖然本人對多維陣列用的也是相當的少,但二維數組,還是有用到的。

4、效能。對,沒錯,PHPRPC的效能仍然無法令我滿意。最明顯的是反射,這個竟然沒有做任何最佳化。

5、不支援實值型別的對象。顯然,PHPRPC並沒有考慮這麼多。

相對第3條、第4條和第5條,第1、2條顯得十分致命,在許多應用程式的開發中,對Dictionary`2或List`1的繼承與擴充是十分頻繁的。綜合PHPRPC的諸多顯著性的缺點,我即將展示我的方案。

·〉我的方案

十分感謝您可以閱讀到這裡,雖然我前面不斷的批評PHPRPC,但它的強大和奇妙,是無法褪去的。尤其是隨著自己的序列化器第一版的落幕,充分體會到PHPRPC其“犧牲”與“得到”(為什麼PHPRPC要這樣做,而不要那樣做)。

只不過——它可以更好。

通過一周左右的鑽研,我發現:任意對象若想要序列化,他無限分解後,只會剩下:基礎資料類型(int、string、DateTime等)和數組,而其餘的,皆為浮雲。

不過這樣的方案是有代價的,尤其是對集合(如Dictionary)的序列化,哪怕集合為空白,也無法瀟洒的簡短。我曾常識對Dictionary進行分解,分成兩個部分,一部分是元素部分,一部分是衍生類別的屬性部分,但最終否決了這樣的方案(考慮集合有可能僅僅是對IDictionary的實現,還有待再次嘗試)。

支援集合的object類型。強大的功能的背後總是效能的犧牲。為了支援一切對象,不得不再次犧牲序列化的大小,在每一個集合的元素前都寫入其類型。這樣的好處是:List<BaseClass>裡含有 DerivedClass,在序列化與還原序列化後不存在任何差異。

在犧牲序列化後的大小,得到的是——任意對象的複製!

為了減少序列化後的大小,我特意增加了一個不影響效能的特性(實際上效能反而令我吃驚的提升了),就是“簡化限定名”(包含對程式集描述進行簡化),例如對於int類型的則為“i”,System.Collections.Generic.List`1則為“scg.List”,支援限定名的命名空間並不多,但是基本覆蓋了常用的,可以大大的簡短序列化後的字串長度。

此次公開Sofire的核心模組之一:Utils源碼(Sofire.Utils,基於.NET 3.5),這個核心架構已經編寫了將近兩年,它包含了幾個核心的功能:Result特性,Emit’s Dynamic Obect、Serialization、Security。如果您有興趣,可以對它進行研究。此次開源僅僅是為了分享,希望可以協助朋友,也希望路過的朋友留下寶貴的意見。接下來附上一張測試圖(PS:測試結果是針對 100000 個對象進行記憶體流序列化,並且 PHPRPC已經是個人進行最佳化的後的版本(拋棄傳統反射帶來的效能損失)

Sofire是一套基於.NET的開發輔助架構。在此段任務忙完以後,可能會針對個人所研發的Sofire Platfrom(資訊化綜合平台)進行講解。

附圖:

源碼(VS2010):

Sofire.Utils架構源碼(包含注釋與說明,開源,沒有任何限制,僅僅有一個小小的請求——請保留原名:Sofire)

效能測試的源碼

最後,如果您喜歡我的文章,或者我的文章可以給您帶來一絲協助,請推薦……

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.