VTD-XMLを使用してXML処理を簡素化する

図3.大きなXMLファイル。フルサイズの画像を表示するには、サムネイルをクリックしてください。

XMLは、開始から8年で、データの保存やWebを介したデータ交換のための、オープンな半構造化データ形式としてすでに普及しています。XMLは、その単純さと人間の可読性により、アプリケーション開発者の間で人気が急上昇し、エンタープライズアーキテクチャの不可欠な部分になっています。

XMLが使用されている方法の数を列挙することは困難ですが、1つのことについて確信が持てます。それは、他のことを行う前にXMLを解析する必要があるということです。実際、適切なパーサーを選択することは、多くの場合、エンタープライズ開発者がプロ​​ジェクトで取り組む必要のある最初の決定の1つです。そして何度も何度も、その決定は2つの一般的なXML処理モデルであるDocument Object Model(DOM)とSimple API for XML(SAX)に帰着します。

一見すると、DOMとSAXのそれぞれの長所と短所は補完的であるように見えます。DOMはメモリ内のオブジェクトグラフを構築します。SAXはイベントベースであり、メモリには何も保存しません。したがって、ドキュメントサイズが小さく、データアクセスパターンが複雑な場合は、DOMが最適です。それ以外の場合は、SAXを使用してください。

しかし、真実はそれほど単純ではありません。多くの場合、開発者はその複雑さのためにSAXを使用することを望んでいませんが、他の実行可能な選択肢がないために使用します。そうしないと、XMLファイルサイズが数百キロバイトよりわずかに大きい場合、DOMのメモリオーバーヘッドとパフォーマンスの低下がアプリケーション開発者にとって困難な障害となり、プロジェクトの最小パフォーマンス目標を達成できなくなります。

しかし、SAXは本当にそれほど優れているのでしょうか? SAXのアドバタイズされた解析パフォーマンス(通常はDOMの数倍高速)は、実際にはしばしば欺かれています。 SAX解析の厄介な前方のみの性質は、追加の実装作業を必要とするだけでなく、ドキュメント構造がわずかに複雑になるとパフォーマンスの低下を招きます。開発者がドキュメントを複数回スキャンしないことを選択した場合、ドキュメントをバッファリングするか、カスタムオブジェクトモデルを構築する必要があります。

いずれにせよ、Apache Axisに例示されているように、パフォーマンスが低下します。 AxisはFAQページで、内部でSAXを使用してパフォーマンスの高い実装を作成すると主張していますが、それでもDOMに非常に似た独自のオブジェクトモデルを構築しているため、以前のバージョン(Apache SOAP)と比較してパフォーマンスの向上はごくわずかです。さらに、SAXはXPathでうまく機能せず、一般にXSLT(Extensible Stylesheet Language Transformation)処理を駆動できません。したがって、SAX解析は、XML処理の実際の問題を回避します。

SAXのより使いやすい代替手段を求めて、ますます多くの開発者がStAX(Streaming API for XML)に目を向けています。SAXと比較すると、StAXパーサーはコールバックを使用する代わりにXMLファイルからトークンをプルします。使いやすさは大幅に向上しますが、基本的な問題は解決しません。StAXのフォワードオンリー解析スタイルには、面倒な実装作業と、それに伴う隠れたパフォーマンスコストが必要です。

結論:XML処理モデルが広く役立つためには、XMLの階層構造を提示する必要があります。その理由は、XMLは複雑なデータをWeb上で移動するように設計されており、構造情報の伝達はXMLの本質的な部分であるためです。

VTD-XMLはゲームを変える

前述のDOMとSAXの問題を克服するために、XML処理を最初から開始するとします。新しいモデルには、おそらく次のプロパティが必要です。

  • ランダムアクセス対応:処理モデルでは、開発者が手動で、またはXPathを使用して、ある種の階層構造をナビゲートできるようにする必要があります。
  • 高性能:パフォーマンスは、DOMおよびSAXよりも大幅に優れている必要があります。また、パフォーマンスは「正直」である必要があります。つまり、測定には、階層構造の構築に費やされた時間が含まれている必要があります。
  • 低メモリ使用量:処理モデルを幅広いシナリオとファイルサイズに適用できるようにするには、最小限のメモリ使用量でXMLの完全な構造を提示する必要があります。

これらの目標を達成するように設計されたVTD-XMLは、DOMおよびSAXに根本的かつ全面的な改善をもたらす次世代のオープンソースXML処理モデルです。 VTD-XMLの重要な最適化の1つは、非抽出トークン化です。内部的には、VTD-XMLは、メモリに無傷でデコードされていないXMLメッセージを保持し、そして排他的に呼ばれるバイナリ符号化仕様に基づいてトークン表すV irtual T王研D escriptorを。 VTDレコードは、トークンの長さ、開始オフセット、タイプ、およびトークンのネストの深さをXMLでエンコードする64ビット整数です。

興味がある場合に備えて、VTD-XMLの歴史を少し紹介します。基本的な概念は、ネットワークスイッチとルーターがXMLを処理できるようにするために、FPGAまたはASICの形式で専用ハードウェアにXML処理を移植する方法として考案されました。非常に高速なコンテンツ。その後、VTD-XMLプロジェクトチームはオープンソースのVTD-XMLを決定し、バージョン0.5の初期リリース(バージョン0.5でJavaに実装)が2004年5月に開始されました。そのリリース以降、VTD-XMLは数回の改善を経て、成熟しました。かなり。バージョン0.8では、JavaバージョンとともにCバージョンのVTD-XMLがリリースされました。組み込みのXPathサポートはバージョン1.0で導入され、2005年10月にリリースされました。最新リリースのバージョン1.5は、よりモジュール化され、より高性能な、書き直された解析エンジンを備えています。

このリリースでは、バッファの再利用と呼ばれる機能も導入されています。基本的な考え方は、ネットワーク接続の背後にあるXMLアプリケーションが多数の受信XMLドキュメントを繰り返し処理する必要がある場合、アプリケーションは最初の処理実行中に割り当てられたメモリバッファーを実際に再利用できるということです。つまり、バッファを1回割り当てて、何度も使用します。VTD-XMLに固有のこの機能により、オブジェクトの作成とガベージコレクションのコスト(DOMおよびSAXのオーバーヘッドの50〜80%)の両方をXML処理から完全に排除できます。プロジェクトのWebサイトには、最新のソフトウェアダウンロードとVTD-XMLの詳細な技術的説明が含まれています。

簡単な例

この記事では、VTD-XMLのプログラミングスタイルを理解するために、まずVTD-XMLとDOMの両方を使用してコードを比較し、test.xmlという名前の単純なXMLファイルを解析してナビゲートします。テキストの内容を以下に示します。

  Lawnmower 1 148.95  

VTD-XMLバージョンは次のようになります。

import com.ximpleware.*; import com.ximpleware.parser.*; import java.io.*;

public class use_vtd { public static void main(String[] args){ try{ File f = new File("test.xml"); FileInputStream fis = new FileInputStream(f); byte[] ba = new byte[(int)f.length()]; fis.read(ba); VTDGen vg = new VTDGen(); vg.setDoc(ba); vg.parse(false); VTDNav vn = vg.getNav(); if (vn.matchElement("purchaseOrder")){ System.out.println(" orderDate==>" + vn.toString(vn.getAttrVal("orderDate"))); if (vn.toElement(VTDNav.FIRST_CHILD,"item")){ if (vn.toElement(VTDNav.FIRST_CHILD)){ do { System.out.print( vn.toString(vn.getCurrentIndex())); System.out.print("==>");

System.out.println( vn.toString(vn.getText())); } while(vn.toElement(VTDNav.NEXT_SIBLING)); } } } } catch (Exception e){ System.out.println("exception occurred ==>"+e); } } }

同じアプリケーションのDOMバージョンを以下に示します。

import java.io.*; import org.w3c.dom.*; import org.w3c.*; import javax.xml.parsers.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.*; import org.xml.sax.SAXException;

public class use_dom { public static void main(String[] args){ try{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = factory.newDocumentBuilder(); Document d= parser.parse("test.xml"); Element root = d.getDocumentElement(); if (root.getNodeName().compareTo("purchaseOrder")==0){ System.out.println(" orderDate==> " + root.getAttribute("orderDate"));

Node n = root.getFirstChild(); if (n != null){ do { if (n.getNodeType() == Node.ELEMENT_NODE && n.getNodeName().compareTo("item")==0){ Node n2 = n.getFirstChild(); if (n2!=null){ do { if (n2.getNodeType() == Node.ELEMENT_NODE){ System.out.println( n2.getNodeName() + "==>" + n2.getFirstChild().getNodeValue() ); } }while((n2=n2.getNextSibling())!=null); } } }while ((n=n.getNextSibling()) != null ); } } } catch (Exception e){ System.out.println("exception occurred ==>"+e); } } }

上記のコード例に示されているように、VTD-XMLはカーソルベースのAPIを使用してXML階層をナビゲートします。対照的に、DOM APIは、オブジェクト参照を要求することによって階層をナビゲートします。VTD-XMLを詳細に説明する技術資料とコード例については、VTD-XMLプロジェクトのWebサイトにアクセスしてください。

VTD-XMLのベンチマーク

Next, let's compare VTD-XML's performance and memory usage with some popular XML parsers. It should be noted that most articles containing benchmark numbers, such as "XML Documents on the Run" by Dennis Sosnoski (JavaWorld, April 2002), are from several years ago. Since then, better and faster hardware are following Moore's Law and becoming cheaper than ever. At the same time, XML parsing and the Java virtual machine have not been standing still—they have seen improvements in many key areas.

Test setup

The test platform is a Sony VAIO laptop equipped with a Pentium M 1.7 GHz processor (2 MB integrated L2 cache) and 512 MB DDR2 RAM. The front bus is clocked at 400 MHz. The OS is Windows XP Professional Edition with services pack 2. The JVM is version 1.5.0_06.

The benchmark tests the latest versions of the following XML parsers:

  • Xerces DOM 2.7.1, with and without deferred node expansion
  • Xerces SAX 2.7.1
  • Piccolo SAX 1.04
  • XPP3 1.1.3.4.O
  • VTD-XML 1.5, with and without buffer reuse

I selected a large collection of XML documents of varying sizes and structural complexities for the test. Depending on the file size, the test documents are grouped into three categories. Small files are less than 10 KB in size. Mid-sized files are between 10 KB and 1 MB. Files larger than 1 MB are considered big.

The server JVM was used for all performance measurements to obtain the peak performance. In those tests, the benchmark programs first looped through the parsing or navigation routines numerous times so that the JVM performed the dynamic, just-in-time optimization of the byte code, before averaging the performance of subsequent iterations as the final results. To reduce timing variation due to disk I/O, the benchmark programs read all XML files into in-memory buffers prior to the test runs.

Note: Interested readers can download the benchmark program from Resources.

Parsing throughput comparisons

このセクションでは、レイテンシとスループットの両方におけるXML解析のパフォーマンスを示します。VTD-XMLとDOMは直接比較できますが、VTD-XMLをSAXまたはPullと比較することは、メモリ内に階層構造を構築しないため、公平ではないことに注意してください。したがって、SAXとプルのパフォーマンスは追加の参照ポイントとしてのみ機能します。

スループット

レイテンシーの比較

表1.小さなファイル

ファイル名/サイズ VTD-XML(ms) VTD-XMLバッファの再利用(ms) SAX(ms) DOM(ms) DOM deferred(ms) ピッコロ(ms) プル(ms)
soap2.xml(1727バイト) 0.0446 0.0346 0.0782 0.1122 0.16225 0.092 0.066
nav_48_0.xml(4608バイト) 0.1054 0.0928 0.266 0.37 0.385 0.2784 0.1742
cd_catalog.xml(5035バイト) 0.118 0.108 0.19 0.348 0.4 0.2 0.214
nav_63_0.xml(6848バイト) 0.149 0.135 0.354 0.513 0.557 0.484 0.242
nav_78_0.xml(6920バイト) 0.153 0.142 0.3704 0.588 0.52 0.42 0.29

表2.中程度のXMLファイル