將 XML 用於數據交換的不斷增長意味著應用程序間發送的 XML 文檔的數量和容量也相應地增長。還沒有跡象表明這種趨勢將來會發生變化,如果說有的話,就是隨著基於 XML 的 Web 服務得到越來越廣泛的支持和應用,這種增長的速度提高了。取得如此成功毫無疑問說明了 XML 對大量應用程序的適用性。
和任何設計一樣,XML 也有一些弱點,其中之一就是把應用程序數據轉化成 XML 表示或者相反所需要的開銷(無論從大小還是處理時間上來說)。這種開銷可能成為許多應用程序總處理代價的主要部分,尤其是那些交換大量數據而內部處理相對較少的應用程序。對於這種類型的應用程序 XML 的很多長處仍然有效,但代價也可能很高。這些代價促使開發人員更深一步考察使用 XML 進行大容量數據交換的權衡問題。
越來越受到關注的一種替代方案是保留 XML 的結構,但為了提高效率采用非本文表示。本文中將討論 XML 的非文本表示所涉及到的一些問題,並介紹為此目的正在開發的幾種方法。第 2 部分將增加一些實際的性能測量數據,以便使您對所能改進的程度有所體會。
文檔大小
數據的 XML 表示往往要比相同數據的二進制表示大得多,主要有兩個原因:
簡單數據值的文本表示通常要比相同值的二進制表示大一些。作為一個極端的例子,單字節的二進制值需要用一到四個字符表示一個帶符號整數文本值(如“0”、“18”或者“-128”)。
XML 是為了清晰性和互操作性而不是簡潔性設計的一種文本標記格式(如 XML 推薦標准“1.1 Origin and Goals”中指出,“簡潔在 XML 標記中最不重要”)。比如說在實踐層面上表現為每個起始標簽必須有匹配的結束標簽。一旦這種冗余與 XML 應用程序中常常使用的相當長的元素和屬性名結合起來,XML 文檔中標記成分的大小可能遠遠超出文檔中實際數據成分的大小。單純為了格式化的目的而增加的空白內容(不是 XML 要求的,但是為了 XML 強調的清晰性而常常使用)進一步增加了文檔大小。
較大的文檔大小意味著傳輸數據的 XML 表示和等價的二進制表示相比需要更多的帶寬。更大的尺寸也意味著更高的處理代價,因為通信過程中涉及到的開銷大部分和數據量有關。
處理開銷
和簡單的二進制數據表示相比,XML 也需要更多的處理開銷。從輸入端來說,XML 文檔處理程序必須識別輸入文檔文本中代表不同標記形式的多種類型的字符組合。處理程序還需要驗證每個文檔是結構良好的 XML,因此在處理標記時必須檢查狀態的轉換。名稱空間雖然是可選的但其應用越來越普遍,它要求通過相關的前綴跟蹤名稱空間的定義,並識別和解除引用(dereference)標記中的元素名和屬性名所用的前綴。最後,文本 XML 數據可能需要轉化成類型化的二進制值,以便接收它的應用程序能夠使用。
XML 文檔輸出也有類似的問題。二進制數據必須首先轉化成文本表示。必須對需要用實體表示的字符數據進行檢查,必須對各種類型的數據創建標記並添加到輸出中。如果使用名稱空間,還必須檢查標記中所用元素名和屬性名的名稱空間 URI,並把 URI 轉化成適當的前綴。
無論輸入還是輸出都需要和 XML 文檔文本所用的特定字符編碼相互轉化,進一步增加了復雜性。XML 處理程序通常被設計成能夠處理多種不同的可能編碼。因此即使兩個應用程序間的文檔交換總是使用某種預先確定的編碼,仍然要付出保證通用性所造成的開銷。
跳出文本的框框
XML 僅僅依據文本定義,因此嚴格地講文本之外的任何東西都不可能是 XML。另一方面,使用 XML 交換數據的應用程序可能更關心傳遞的數據,而不是嚴格的 XML 表示。根據您願意在多大程度上堅持 XML 的文本特性,可以選擇多種不同的技術減少文檔大小、提高處理速度或者兩者兼備。這一節我將介紹其中的三類技術。
一般的文本轉換
專門為 XML 設計的編碼
為特定 XML 應用程序量身定做的格式
文本至上:一般的文本轉換
最嚴格遵循 XML 文本特性的技術是一般基於文本的轉換。這種類型的轉換主要和文檔大小有關。文本壓縮算法多年來一直是大量研究項目的課題,目前已經非常成熟。這種類型的任何算法都能方便地用於 XML 文檔的文本表示。這類算法不大可能改善處理速度,因為實際上在普通的 XML 文本處理之外,它們在應用程序間數據流的兩端增加了一層轉換:在發送端壓縮文本,然後在接收端解壓縮。
gzip是一種廣泛使用的文本文檔壓縮算法,在許多平台上都有實現,包括標准的 Java 庫。在第 2 部分,我將討論基於 Java 的性能測試結果,其中包括 gzip 作為一種可選方案。
堅持信仰:為 XML 專門設計編碼
在保留文本 XML 文檔中真正重要內容的同時,還可以比一般的基於文本的轉換更進一步。設計這種類型的方法是為了通過某種編碼表示,以能夠減少文檔大小、降低處理開銷或者兩方面兼具的方式利用 XML 的結構。從編碼形式上重新構造原來的文檔,僅僅損失 XML 認為無關的那些信息(因為任何 XML 處理程序通常會忽略這類信息,如屬性間的空格數、包圍屬性值的引號類型以及屬性的順序)通常是可能的。由於損失了信息,原始文檔和重新構造的文檔進行直接文本比較可能不同,但是對於符合 XML 規則的任何應用程序而言它們是等價的。
我把保留文檔 XML 視圖的轉換稱為 XML 編碼(XML encoding)。 從 XML 到 XML 編碼的轉換應該保留任何有效 XML 文檔的完整 XML 視圖。一般而言這很難證明,不過 XML Canonicalization 推薦標准給出了一種實用性的測試方法:它詳細規定了如何把 XML 文檔轉化成一種標准形式,以便確定文檔在邏輯上是否等價,它是很多關於保護和簽署 XML 數據的研究項目的基礎。當且僅當編碼輸入文檔的規范形式和重新構造的文檔的規范形式總能保持一致時,才稱這種 XML 數據表示技術是一種 XML 編碼,這樣說似乎是合理的。如果對於某個合理的文檔,該技術不能通過這一測試,就不能認為是一種 XML 編碼。
XMill(請參閱 參考資料)是 XML 轉換的一個很好的例子,其目的是為了壓縮文檔的大小。XMill 與 gzip 壓縮結合使用,主要是重新安排文檔文本使其更容易壓縮。其中包括幾個步驟:首先用整數代碼值代替實際元素的起始和結束標簽,單獨進行壓縮;然後所有元素類型的字符數據組成塊單獨壓縮;對每種類型的元素重復後一個步驟(XMill 也允許定制每種元素類型,但這裡先忽略這個問題)。通過用這種方式把類似的數據組織在一起,gzip 可以更有效地操作。最終的結果是以大約相同的處理代價(總起來看甚至更少),得到了比單純使用 gzip 更小的文檔。從描述上看還不很清楚 XMill 是否符合上述意義上的 XML 編碼,但無疑能夠成為這樣一種編碼技術。
可以使用其他技術獲得比文本 XML 更好的文檔處理速度。這些較快的技術通常是通過一個過程減少 XML 文檔中的冗余,同時使其更容易處理。這聽起來似乎自相矛盾——如果減少了冗余,文檔似乎應該更難以處理而不是更容易——但實際上這兩個目標可以很好地配合。同時符合兩個目標的轉換包括用更緊湊的形式置換元素名和屬性名,使用計數或者記號代替結束標簽,去掉老套的模式(如包圍屬性值的 ="..." 文本),有時候還可以重用重復的字符數據內容值。
我自己的開放源代碼項目 XML Binary Infoset(XML 二進制信息集,XBIS,請參閱 參考資料)定義了一種編碼技術,其設計目標是保留文檔的 XML 視圖,把前面所述的各種轉換和文檔成分的高效壓縮字節表示結合起來。 XBIS 的重點是 處理速度而不是文檔大小,但通常和文本相比確實能減小文檔的大小,同時又提高了處理速度。XBIS 保留了我曾經測試過的所有 XML 文檔的規范形式,從這個意義上說,它是一種完整的 XML 編碼。(將來也許會發現某些不同尋常的文檔破壞了這一條,但如果這樣,我會在 XBIS 表式中增加任何被忽視的信息。)
雖然 XBIS 和 XMill 有一些類似之處(包括用數字代碼代替元素名),但兩者采用了完全不同的方法。XMill 本質上是一種全文檔轉換(和 gzip 本身一樣),就是說必須一次處理文檔的全部文本。這意味著需要編碼和解碼 XMill 表示,因此 XMill(或者單純的 gzip)在處理系統間傳輸的文檔時可能增加了響應的延遲時間。另一方面,XBIS 是一種流式的轉換,編碼和解碼都是動態完成的。這種區別和 XMill 強調文檔大小而 XBIS 強調速度是一致的:如果主要關心大小,增加一些延遲和處理開銷把大小降到最低可能是值得的;但是如果主要關心速度,轉移的時候盡量減少阻塞的時間通常更好一些。
我個人認為,XML 編碼和對文本文檔使用 gzip 在邏輯上是等價的。但並非每個人都同意這種觀點,對於一些極其崇拜 XML 的開發人員而言,改變文檔文本表示的任何形式的轉換(即使以和 XML 無關的方式)都是對文檔的扭曲。對於這些開發人員而言,允許使用 gzip 是因為它可以重新構造和原始文檔完全相同的文本,但不能完全保留文本的任何 XML 編碼方法都是不允許的。對於尋求無格式文本或者文本壓縮的替代方法的任何項目的開發人員而言,這可能是需要考慮的一個問題。
數據至上:為特定 XML 應用程序量身定做的格式
為特定 XML 應用程序專門設計的格式是和基於文本的壓縮相對的另一個極端。這些格式可能和數據的純二進制表示等價,和文本 XML 相比有可能同時壓縮數據的大小並減少處理開銷。這種方法的主要缺點是必須根據應用程序使用的文檔結構量身定做,發送方和接收方必須事先就具體的結構達成一致,並且實現適當的編碼程序/解碼程序。
針對應用程序定制編碼的多數方法都是基於交換文檔的 W3C XML Schema 規范。模式中包含的類型和結構信息用於生成定制的編碼程序/解碼程序代碼,可能包括能夠代表文檔數據內容並直接與編碼程序/解碼程序交互的對象。Fast Web Services(請參閱 參考資料)是從模式定制編碼的一個例子,它建立在 ASN.1 結構化數據表述的基礎上。
這種類型的模式編碼很難與處理一般 XML 文檔的其他方法比較(類型不一定相同,也不一定有模式)。為了測試各種文檔,首先必須為每個文檔定義模式,然後生成這種模式的編碼程序/解碼程序代碼。用當前的實現完成這種數據表示和標准 XML 文本形式的轉化一般是不可能的,因此還需要編寫某種自定義的轉化程序,以便把標准文本 XML 文檔轉化成可以使用這種編碼的形式。由於這些原因,我的測試結果中沒有包括這種方法的例子,但是在您看過這些結果之後,我還將再提一提模式編碼的使用。
結束語
現在我已經介紹了關於為何以及如何使用 XML 的非文本表示的背景,後面將考察這樣做所能帶來的好處。第 2 部分將說明如何測試一些文檔的文本、gzip 和 XBIS 表示。我還將說明和討論測試的結果,然後看一看這一領域目前正在進行的一些活動。