Permudahkan pemprosesan XML dengan VTD-XML

Rajah 3. Fail XML besar. Klik gambar kecil untuk melihat gambar bersaiz penuh.

Lapan tahun sejak penubuhannya, XML telah menjadi format data semi-berstruktur terbuka untuk menyimpan data dan juga pertukaran data melalui Web. Kerana kesederhanaan dan kebolehbacaan manusia, XML telah melihat popularitinya meroket di kalangan pembangun aplikasi dan telah menjadi bahagian yang sangat diperlukan dalam seni bina perusahaan.

Walaupun sukar untuk menghitung jumlah cara XML digunakan, seseorang dapat memastikan satu perkara: XML mesti diuraikan sebelum perkara lain dapat dilakukan. Sebenarnya, memilih penghurai yang tepat sering kali menjadi salah satu keputusan pertama yang mesti ditangani oleh pemaju perusahaan dalam projek mereka. Sekali lagi, keputusan itu diturunkan kepada dua model pemprosesan XML yang popular: Model Objek Dokumen (DOM) dan API Mudah untuk XML (SAX).

Pada pandangan pertama, kekuatan dan kelemahan masing-masing DOM dan SAX kelihatan saling melengkapi: DOM membina grafik objek dalam memori; SAX berasaskan acara dan tidak menyimpan apa-apa dalam memori. Oleh itu, jika saiz dokumen kecil dan corak akses data yang kompleks, DOM adalah cara yang tepat; jika tidak, gunakan SAX.

Walau bagaimanapun, kebenaran tidak pernah sesederhana itu. Lebih kerap daripada itu, pembangun tidak mahu menggunakan SAX kerana kerumitannya, namun masih melakukannya kerana tidak ada pilihan lain yang sesuai. Jika tidak, jika ukuran fail XML hanya sedikit lebih besar daripada beberapa ratus kilobyte, overhead memori DOM dan seretan prestasi menjadi penghalang yang sukar bagi pembangun aplikasi, yang menghalangnya daripada memenuhi tujuan prestasi minimum projek mereka.

Tetapi adakah SAX jauh lebih baik? Prestasi penghuraian SAX yang diiklankan — biasanya beberapa kali lebih cepat daripada DOM — sebenarnya sering menipu. Ternyata penghuraian SAX yang canggung dan maju bukan sahaja memerlukan usaha pelaksanaan tambahan, tetapi juga dikenakan penalti prestasi apabila struktur dokumen menjadi sedikit rumit. Sekiranya pembangun memilih untuk tidak mengimbas dokumen berkali-kali, mereka harus menyangga dokumen atau membina model objek tersuai.

Walau apa pun, prestasi menderita, seperti yang ditunjukkan oleh Apache Axis. Di halaman Soalan Lazimnya, Axis mengaku menggunakan SAX secara dalaman untuk membuat implementasi yang berkinerja lebih tinggi, namun ia masih membina model objeknya sendiri yang mirip DOM, menghasilkan peningkatan prestasi yang tidak dapat dibandingkan jika dibandingkan dengan pendahulunya (Apache SOAP). Selain itu, SAX tidak berfungsi dengan baik dengan XPath, dan secara umum tidak dapat mendorong pemprosesan XSLT (Extensible Stylesheet Language Transformation). Oleh itu, SAX menguraikan masalah sebenar pemprosesan XML.

Mencari alternatif yang lebih mudah digunakan untuk SAX, semakin banyak pembangun telah beralih ke StAX (Streaming API untuk XML). Berbanding dengan SAX, penyusun StAX menarik token dari fail XML dan bukannya menggunakan panggilan balik. Walaupun ketara meningkatkan kebolehgunaan, masalah mendasar tetap ada - gaya penghuraian hanya hadapan StAX masih memerlukan usaha pelaksanaan yang membosankan dan, seiring dengannya, kos prestasi tersembunyi.

Intinya: Agar model pemprosesan XML berguna secara meluas, ia mesti menunjukkan struktur hierarki XML dan tidak kurang. Sebabnya adalah kerana XML dirancang untuk memindahkan data yang kompleks melalui Web, dan menyampaikan maklumat struktur adalah bahagian yang melekat dari apa yang dilakukan oleh XML.

VTD-XML mengubah permainan

Andaikan kita memulakan pemprosesan XML dari awal untuk mengatasi masalah yang disebutkan sebelumnya dengan DOM dan SAX. Model baru mungkin mempunyai sifat berikut:

  • Akses rawak yang mampu dilakukan: Model pemprosesan harus membolehkan pemaju menavigasi semacam struktur hierarki sama ada secara manual atau, lebih baik, dengan menggunakan XPath.
  • Prestasi tinggi: Prestasi harus jauh lebih baik daripada DOM dan SAX. Dan persembahan harus "jujur," yang bermaksud pengukuran mesti merangkumi masa yang dihabiskan untuk membina struktur hierarki.
  • Penggunaan memori rendah: Untuk menjadikan model pemrosesan berlaku untuk berbagai macam senario dan ukuran file, ia harus menunjukkan struktur penuh XML dengan jumlah penggunaan memori minimum.

Direka untuk memenuhi tujuan tersebut, VTD-XML adalah model pemprosesan XML sumber terbuka generasi seterusnya yang membawa peningkatan asas dan menyeluruh berbanding DOM dan SAX. Salah satu pengoptimuman utama VTD-XML adalah tokenisasi tidak ekstraktif. Secara dalaman, VTD-XML menyimpan dalam ingatan mesej XML yang utuh dan tidak dikodkan, dan mewakili token secara eksklusif berdasarkan spesifikasi pengekodan binari yang disebut V irtual T oken D escriptor. Rekod VTD adalah bilangan bulat 64-bit yang menyandikan panjang token, memulakan ofset, jenis, dan kedalaman token bersarang dalam XML.

Berikut adalah sedikit sejarah VTD-XML sekiranya anda berminat: Konsep asas ini difikirkan sebagai cara untuk mengangkut pemprosesan XML pada perkakasan khusus, dalam bentuk FPGA atau ASIC, untuk membolehkan suis dan penghala rangkaian memproses XML kandungan pada kelajuan yang sangat tinggi. Kemudian, pasukan projek VTD-XML memutuskan untuk membuka sumber VTD-XML, dan pelepasan awal - versi 0.5 dan dilaksanakan di Java - berlaku pada bulan Mei 2004. Sejak peluncuran itu, VTD-XML telah mengalami beberapa putaran penambahbaikan dan matang banyak. Dalam versi 0.8, versi C dari VTD-XML dirilis bersama dengan versi Java. Sokongan XPath bawaan diperkenalkan pada versi 1.0 dan dirilis pada bulan Oktober 2005. Rilis terbaru, versi 1.5, menampilkan mesin parsing yang ditulis semula yang lebih modular dan berkinerja lebih tinggi.

Juga diperkenalkan dalam rilis ini adalah fitur yang disebut buffer reuse. Idea asasnya ialah apabila aplikasi XML yang berada di belakang sambungan rangkaian perlu memproses berulang-ulang banyak dokumen XML yang masuk, aplikasi tersebut sebenarnya dapat menggunakan kembali buffer memori yang diperuntukkan selama proses pemprosesan pertama. Dengan kata lain, peruntukkan penyangga sekali dan gunakannya berkali-kali. Khusus untuk VTD-XML, ciri ini memungkinkan penghapusan sepenuhnya penciptaan objek dan kos pengumpulan sampah (50-80 peratus overhead di DOM dan SAX) dari pemprosesan XML. Laman web projek mengandungi muat turun perisian terkini dan penerangan teknikal mendalam mengenai VTD-XML.

Contoh ringkas

Untuk memberikan gambaran gaya pengaturcaraan VTD-XML, artikel ini terlebih dahulu membandingkan kod menggunakan VTD-XML dan DOM untuk menguraikan dan menavigasi fail XML sederhana bernama test.xml, yang kandungan teksnya ditunjukkan di bawah:

  Lawnmower 1 148.95  

Versi VTD-XML kelihatan seperti ini:

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); } } }

Versi DOM dari aplikasi yang sama ditunjukkan di bawah:

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); } } }

Seperti yang digambarkan dalam contoh kod di atas, VTD-XML menavigasi hierarki XML menggunakan API berasaskan kursor. Sebaliknya, API DOM menavigasi hierarki dengan meminta rujukan objek. Sila kunjungi Laman Web projek VTD-XML untuk mendapatkan lebih banyak bahan teknikal dan contoh kod yang menjelaskan VTD-XML dengan mendalam.

Penanda Aras 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

Bahagian ini menunjukkan prestasi menguraikan XML dalam kedua-dua latensi dan throughput. Perhatikan bahawa walaupun VTD-XML dan DOM dapat dibandingkan secara langsung, tidak adil untuk membandingkan VTD-XML dengan SAX atau Tarik kerana mereka tidak membina struktur hierarki dalam memori. Jadi prestasi untuk SAX dan Pull hanya berfungsi sebagai titik rujukan tambahan.

Throughput

Perbandingan kependaman

Jadual 1. Fail kecil

Nama / saiz fail VTD-XML (ms) Penggunaan semula buffer VTD-XML (ms) SAX (ms) DOM (ms) DOM ditangguhkan (ms) Piccolo (ms) Tarik (ms)
sabun2.xml (1727 bait) 0.0446 0.0346 0.0782 0.1122 0.16225 0.092 0.066
nav_48_0.xml (4608 bait) 0.1054 0.0928 0.266 0.37 0.385 0.2784 0.1742
cd_catalog.xml (5035 bait) 0.118 0.108 0.19 0.348 0.4 0.2 0.214
nav_63_0.xml (6848 bait) 0.149 0.135 0.354 0.513 0.557 0.484 0.242
nav_78_0.xml (6920 bait) 0.153 0.142 0.3704 0.588 0.52 0.42 0.29

Jadual 2. Fail XML sederhana