Programmering

Forenkle XML-behandling med VTD-XML

Figur 3. Store XML-filer. Klikk på miniatyrbildet for å se bildet i full størrelse.

Åtte år siden oppstarten, har XML allerede tatt av som et åpent, semi-strukturert dataformat for lagring av data samt utveksling av data via nettet. På grunn av sin enkelhet og menneskelige lesbarhet har XML sett populariteten skyte i været blant applikasjonsutviklere og har blitt en uunnværlig del av bedriftsarkitekturen.

Selv om det er vanskelig å oppregne antall måter XML brukes, kan man være sikker på én ting: XML må analyseres før noe annet kan gjøres. Å velge riktig parser er ofte en av de første beslutningene som bedriftsutviklere må takle i prosjektene sine. Og igjen og igjen kommer beslutningen ned til de to populære XML-behandlingsmodellene: Document Object Model (DOM) og Simple API for XML (SAX).

Ved første øyekast virker de respektive styrkene og svakhetene til DOM og SAX komplementære: DOM bygger objektgrafer i minnet; SAX er hendelsesbasert og lagrer ingenting i minnet. Så hvis dokumentstørrelsen er liten og datatilgangsmønsteret er komplisert, er DOM veien å gå; ellers, bruk SAX.

Sannheten er imidlertid aldri så forenklet. Oftere enn ikke er utviklere uvillige til å bruke SAX på grunn av kompleksiteten, men gjør det fortsatt fordi det ikke er noe annet levedyktig valg tilgjengelig. Ellers, hvis XML-filstørrelsen bare er litt større enn noen få hundre kilobyte, blir DOMs minneomkostninger og ytelsesmotstand en tøff veisperring for applikasjonsutviklere, og forhindrer dem i å oppfylle prosjektenes minimum ytelsesmål.

Men er SAX virkelig så mye bedre? SAXs annonserte analyseringsytelse - vanligvis flere ganger raskere enn DOM - lurer ofte ofte. Det viser seg at den vanskelige, fremadrettede karakteren til SAX-parsing ikke bare krever ekstra implementeringsinnsats, men også medfører ytelsesstraffer når dokumentstrukturen bare blir litt kompleks. Hvis utviklere velger å ikke skanne dokumentet flere ganger, må de buffere dokumentet eller bygge tilpassede objektmodeller.

Uansett lider ytelsen, som eksempler på Apache Axis. På FAQ-siden hevder Axis at den internt bruker SAX for å skape en implementering med høyere ytelse, men likevel bygger den sin egen objektmodell som er ganske DOM-lignende, noe som resulterer i ubetydelige ytelsesforbedringer sammenlignet med forgjengeren (Apache SOAP). I tillegg fungerer ikke SAX bra med XPath, og kan generelt ikke drive XSLT (Extensible Stylesheet Language Transformation) -behandling. Så SAX-parsing skjørt de virkelige problemene med XML-behandling.

På jakt etter et brukervennlig alternativ til SAX, har et økende antall utviklere henvendt seg til StAX (Streaming API for XML). Sammenlignet med SAX trekker StAX-parsere tokens fra XML-filer i stedet for å bruke tilbakekall. Mens de forbedrer brukervennligheten, vedvarer de grunnleggende problemene - StAXs fremadrettede analysestil krever fortsatt kjedelig implementeringsarbeid og sammen med det skjulte ytelseskostnader.

Poenget: For at en hvilken som helst XML-behandlingsmodell skal være nyttig, må den presentere den hierarkiske strukturen til XML og ikke noe mindre. Årsaken er fordi XML er designet for å flytte komplekse data over nettet, og å formidle strukturell informasjon er en iboende del av det XML gjør.

VTD-XML endrer spillet

Anta at vi skulle starte XML-prosessering fra bunnen av for å løse de nevnte problemene med DOM og SAX. Den nye modellen skal sannsynligvis ha følgende egenskaper:

  • Tilfeldig tilgang i stand: Behandlingsmodellen skal tillate utvikleren å navigere i en slags hierarkisk struktur enten manuelt eller, bedre, ved å bruke XPath.
  • Høy ytelse: Ytelsen skal være vesentlig bedre enn DOM og SAX. Og ytelsen skal være "ærlig", noe som betyr at målingen må omfatte tiden brukt på å bygge den hierarkiske strukturen.
  • Lav minnebruk: For å gjøre prosesseringsmodellen gjeldende for et bredt spekter av scenarier og filstørrelser, må den presentere den fulle strukturen til XML med et minimum av minnebruk.

VTD-XML er designet for å oppfylle disse målene, og er neste generasjons XML-prosesseringsmodell med åpen kildekode som gir grunnleggende forbedringer og forbedringer over DOM og SAX. En nøkkeloptimalisering av VTD-XML er ikke-utvinnende tokenisering. Internt beholder VTD-XML den intakte og udekodede XML-meldingen i minnet, og representerer tokens utelukkende basert på en spesifikasjon for binær koding kalt Virtual Token Deskriptor. En VTD-post er et 64-biters heltall som koder tokenlengden, startforskyvning, type og nestedybde for et token i XML.

Her er litt av historien til VTD-XML i tilfelle du er interessert: Det grunnleggende konseptet ble oppfattet som en måte å portere XML-prosessering på dedikert maskinvare, i form av FPGA eller ASIC, for å aktivere nettverkssvitsjer og rutere til å behandle XML innhold i veldig høye hastigheter. Senere bestemte VTD-XML-prosjektgruppen seg for å åpne kildekoden VTD-XML, og den første utgivelsen - av versjon 0.5 og implementert i Java - fant sted i mai 2004. Siden den utgivelsen har VTD-XML gjennomgått flere forbedringsrunder og modnet mye. I versjon 0.8 ble C-versjonen av VTD-XML utgitt sammen med Java-versjonen. Innebygd XPath-støtte ble introdusert i versjon 1.0 og utgitt i oktober 2005. Den siste utgivelsen, versjon 1.5, har en omskrevet parsing-motor som er mer modulær og gir bedre ytelse.

Også introdusert i denne utgivelsen er en funksjon som kalles buffer gjenbruk. Den grunnleggende ideen er at når et XML-program som sitter bak en nettverkstilkobling trenger å behandle mange innkommende XML-dokumenter gjentatte ganger, kan applikasjonen faktisk gjenbruke minnebuffere som er tildelt i løpet av den første prosesseringen. Med andre ord, tildel buffere en gang og bruk dem mange, mange ganger. Spesifikt for VTD-XML, tillater denne funksjonen fullstendig eliminering av både gjenstandsoppretting og søppeloppsamlingskostnad (50-80 prosent av overhead i DOM og SAX) fra XML-behandling. Prosjektet Nettsted inneholder de nyeste programvarnedlastningene og en grundig teknisk beskrivelse av VTD-XML.

Et raskt eksempel

For å gi en følelse av VTD-XMLs programmeringsstil, sammenligner denne artikkelen først kode ved bruk av både VTD-XML og DOM for å analysere og navigere i en enkel XML-fil med navnet test.xml, hvis tekstinnhold er vist nedenfor:

  Gressklipper 1 148,95 

VTD-XML-versjonen ser slik ut:

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

public class use_vtd {public static void main (String [] args) {try {File f = new File ("test.xml"); FileInputStream fis = ny FileInputStream (f); byte [] ba = ny byte [(int) f.lengde ()]; fis.read (ba); VTDGen vg = nye 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 ())); } mens (vn.toElement (VTDNav.NEXT_SIBLING)); }}}} fangst (Unntak e) {System.out.println ("unntak oppstod ==>" + e); }}}

DOM-versjonen av samme applikasjon er vist nedenfor:

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

public class use_dom {public static void main (String [] args) {try {DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance (); DocumentBuilder parser = factory.newDocumentBuilder (); Dokument d = parser.parse ("test.xml"); Elementrot = 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 (). comparTo ("item") == 0) {Node n2 = n.getFirstChild (); if (n2! = null) {do {if (n2.getNodeType () == Node.ELEMENT_NODE) ​​{System.out.println (n2.getNodeName () + "==>" + n2.getFirstChild (). getNodeValue ( )); }} mens ((n2 = n2.getNextSibling ())! = null); }}} mens ((n = n.getNextSibling ())! = null); }}} fangst (Unntak e) {System.out.println ("unntak oppstod ==>" + e); }}}

Som illustrert i kodeeksemplene ovenfor, navigerer VTD-XML i XML-hierarkiet ved hjelp av et markørbasert API. I kontrast navigerer DOM API i hierarkiet ved å be om objektreferanser. Vennligst besøk VTD-XML-prosjektets nettsted for mer teknisk materiale og kodeeksempler som forklarer VTD-XML i stor dybde.

Benchmarking av VTD-XML

La oss deretter sammenligne ytelsen og minnebruk av VTD-XML med noen populære XML-parsere. Det bør bemerkes at de fleste artikler som inneholder referansenummer, for eksempel "XML Documents on the Run" av Dennis Sosnoski (JavaWorld, April 2002), er fra flere år siden. Siden da følger bedre og raskere maskinvare Moores lov og blir billigere enn noensinne. Samtidig har ikke XML-parsing og den virtuelle Java-maskinen stått stille - de har sett forbedringer på mange viktige områder.

Testoppsett

Testplattformen er en bærbar Sony VAIO utstyrt med en Pentium M 1,7 GHz-prosessor (2 MB integrert L2-cache) og 512 MB DDR2 RAM. Frontbussen er klokket på 400 MHz. Operativsystemet er Windows XP Professional Edition med servicepakke 2. JVM er versjon 1.5.0_06.

Referansen tester de nyeste versjonene av følgende XML-parsere:

  • Xerces DOM 2.7.1, med og uten utsatt nodeutvidelse
  • Xerces SAX 2.7.1
  • Piccolo SAX 1.04
  • XPP3 1.1.3.4.O
  • VTD-XML 1.5, med og uten buffergjenbruk

Jeg valgte en stor samling av XML-dokumenter av forskjellige størrelser og strukturelle kompleksiteter for testen. Avhengig av filstørrelse, er testdokumentene gruppert i tre kategorier. Små filer er mindre enn 10 kB store. Mellomstore filer er mellom 10 KB og 1 MB. Filer større enn 1 MB regnes som store.

Serveren JVM ble brukt til alle ytelsesmålinger for å oppnå topp ytelse. I disse testene gikk referanseprogrammene først gjennom parsings- eller navigasjonsrutinene flere ganger, slik at JVM utførte den dynamiske, akkurat-i-tid-optimaliseringen av byte-koden, før den gjennomsnittlige ytelsen til påfølgende iterasjoner som de endelige resultatene. For å redusere tidsvariasjoner på grunn av disk I / O, leser referanseprogrammene alle XML-filer i buffere i minnet før testkjøringene.

Merk: Interesserte lesere kan laste ned referanseprogrammet fra Resources.

Analyse av gjennomstrømnings sammenligninger

Denne delen presenterer XML-parseringsytelsen i både ventetid og gjennomstrømning. Legg merke til at mens VTD-XML og DOM er direkte sammenlignbare, er det ikke rettferdig å sammenligne VTD-XML med SAX eller Pull fordi de ikke bygger noen hierarkisk struktur i minnet. Så ytelse for SAX og Pull fungerer bare som et ekstra referansepunkt.

Gjennomstrømning

Latens sammenligninger

Tabell 1. Små filer

Filnavn / størrelseVTD-XML (ms)Gjenbruk av VTD-XML-buffer (ms)SAX (ms)DOM (ms)DOM utsatt (ms)Piccolo (ms)Trekk (ms)
soap2.xml (1727 bytes)0.04460.03460.07820.11220.162250.0920.066
nav_48_0.xml (4608 byte)0.10540.09280.2660.370.3850.27840.1742
cd_catalog.xml (5035 byte)0.1180.1080.190.3480.40.20.214
nav_63_0.xml (6848 byte)0.1490.1350.3540.5130.5570.4840.242
nav_78_0.xml (6920 byte)0.1530.1420.37040.5880.520.420.29

Tabell 2. Medium XML-filer

$config[zx-auto] not found$config[zx-overlay] not found