Опростете XML обработката с VTD-XML

Фигура 3. Големи XML файлове. Щракнете върху миниизображение, за да видите изображение в пълен размер.

Осем години от създаването си, XML вече е стартирал като отворен, полуструктуриран формат за данни за съхранение на данни, както и за обмен на данни в мрежата. Поради своята простота и четливост за хора, XML е видял своята популярност скок в средите на разработчиците на приложения и се е превърнал в незаменима част от корпоративната архитектура.

Въпреки че е трудно да се изброи броят на начините, по които се използва XML, човек може да бъде сигурен в едно нещо: XML трябва да се анализира, преди да може да се направи нещо друго. Всъщност изборът на подходящ парсер често е едно от първите решения, с които разработчиците на предприятия трябва да се справят в своите проекти. И отново и отново, това решение се свежда до двата популярни XML модела за обработка: Document Object Model (DOM) и Simple API за XML (SAX).

На пръв поглед съответните силни и слаби страни на DOM и SAX изглеждат допълващи се: DOM изгражда графики на обекти в паметта; SAX е базиран на събития и не съхранява нищо в паметта. Така че, ако размерът на документа е малък и моделът за достъп до данни е сложен, DOM е пътят; в противен случай използвайте SAX.

Истината обаче никога не е толкова опростена. По-често разработчиците не желаят да използват SAX поради неговата сложност, но все още го правят, тъй като не е наличен друг възможен избор. В противен случай, ако размерът на XML файла е малко по-голям от няколко стотици килобайта, натоварването на паметта на DOM и плъзгането на производителността се превръщат в трудно препятствие за разработчиците на приложения, което им пречи да изпълнят минималните цели за изпълнение на своите проекти.

Но наистина ли SAX е толкова по-добър? Рекламираната ефективност на SAX за синтактичен анализ - обикновено няколко пъти по-бърза от DOM - всъщност често заблуждава. Оказва се, че неудобният, само за напред характер на разбор на SAX не само изисква допълнителни усилия за внедряване, но и налага наказания за изпълнение, когато структурата на документа стане само леко сложна. Ако разработчиците изберат да не сканират документа няколко пъти, ще трябва да буферират документа или да създадат персонализирани обектни модели.

Така или иначе, производителността страда, както е показано от Apache Axis. На своята страница с често задавани въпроси Axis твърди, че използва вътрешно SAX, за да създаде по-ефективна имплементация, но все пак изгражда свой собствен обектен модел, който е доста DOM-подобен, което води до незначително подобрение на производителността в сравнение с предшественика си (Apache SOAP). Освен това SAX не работи добре с XPath и като цяло не може да управлява обработка на XSLT (Extensible Stylesheet Language Transformation). Така че SAX парсирането заобикаля истинските проблеми на XML обработката.

Търсейки по-лесна за използване алтернатива на SAX, все по-голям брой разработчици са се насочили към StAX (Streaming API за XML). В сравнение със SAX, анализаторите на StAX изтеглят маркери от XML файлове, вместо да използват обратно извикване. Въпреки че те значително подобряват използваемостта, основните проблеми продължават да съществуват - стилът за синтактичен анализ на StAX все още изисква досадни усилия за внедряване и заедно с това скрити разходи за производителност.

Изводът: За да може всеки XML модел за обработка да бъде широко полезен, той трябва да представя йерархичната структура на XML и нищо по-малко. Причината е, че XML е предназначен за преместване на сложни данни през мрежата и предаването на структурна информация е неразделна част от това, което XML прави.

VTD-XML променя играта

Да предположим, че трябва да започнем XML обработка от нулата, за да преодолеем гореспоменатите проблеми с DOM и SAX. Новият модел вероятно трябва да има следните свойства:

  • Възможност за произволен достъп: Моделът за обработка трябва да позволява на разработчика да се движи по някаква йерархична структура или ръчно, или по-добре, като използва XPath.
  • Висока производителност: Производителността трябва да бъде значително по-добра от DOM и SAX. И представянето трябва да бъде "честно", което означава, че измерването трябва да включва времето, изразходвано за изграждане на йерархичната структура.
  • Ниско използване на паметта: За да направи модела на обработка приложим за широк спектър от сценарии и размери на файлове, той трябва да представя пълната структура на XML с минимално количество използване на паметта.

Проектиран да изпълни тези цели, VTD-XML е следващото поколение XML модел за обработка с отворен код, който носи основни и всеобхватни подобрения над DOM и SAX. Една от ключовите оптимизации на VTD-XML е неекстрактивна токенизация. Вътрешно VTD-XML запазва в паметта непокътнатото и некодирано XML съобщение и представлява символи, базирани изключително на двоична спецификация за кодиране, наречена V irtual T oken D escriptor. Записът VTD е 64-битово цяло число, което кодира дължината на маркера, начално отместване, тип и дълбочина на влагане на маркер в XML.

Ето малко история на VTD-XML, в случай че се интересувате: Основната концепция е замислена като начин за пренасяне на XML обработка на специален хардуер, под формата на FPGA или ASIC, за да се даде възможност на мрежовите комутатори и рутери да обработват XML съдържание на много високи скорости. По-късно екипът на проекта VTD-XML реши да отвори VTD-XML с отворен код и първоначалната версия - на версия 0.5 и внедрена в Java - се състоя през май 2004 г. От тази версия VTD-XML претърпя няколко кръга от подобрения и узрее значително. Във версия 0.8 беше пусната C версията на VTD-XML заедно с версията на Java. Вградената поддръжка на XPath е въведена във версия 1.0 и пусната през октомври 2005 г. Последната версия, версия 1.5, включва пренаписан механизъм за синтактичен анализ, който е по-модулен и с по-висока производителност.

Също така в тази версия е представена функция, наречена повторно използване на буфера. Основната идея е, че когато XML приложение, разположено зад мрежова връзка, трябва да обработва многократно много входящи XML документи, приложението може да използва повторно буферите на паметта, разпределени по време на първото изпълнение на обработката. С други думи, разпределете буферите веднъж и ги използвайте много, много пъти. Специфично за VTD-XML, тази функция позволява пълното елиминиране както на създаването на обекти, така и на разходите за събиране на боклука (50-80 процента от режийните в DOM и SAX) от XML обработката. Уебсайтът на проекта съдържа най-новите изтегляния на софтуер и задълбочено техническо описание на VTD-XML.

Бърз пример

За да даде представа за стила на програмиране на VTD-XML, тази статия първо сравнява кода, използвайки VTD-XML и DOM, за да анализира и навигира прост XML файл с име test.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 навигира в XML йерархията, използвайки API, базиран на курсора. За разлика от това, DOM API навигира в йерархията, като изисква препратки към обекти. Моля, посетете уебсайта на проекта VTD-XML за повече технически материали и примери за кодове, които обясняват VTD-XML задълбочено.

Бенчмаркинг VTD-XML

След това нека сравним производителността и използването на паметта на VTD-XML с някои популярни XML парсери. Трябва да се отбележи, че повечето статии, съдържащи референтни номера, като "XML документи в движение" от Денис Сосноски ( JavaWorld , април 2002 г.), са от преди няколко години. Оттогава по-добрият и по-бърз хардуер следва закона на Мур и става по-евтин от всякога. В същото време разборът на XML и виртуалната машина Java не стоят на едно място - те са забелязали подобрения в много ключови области.

Тестова настройка

Тестовата платформа е лаптоп Sony VAIO, оборудван с процесор Pentium M 1,7 GHz (2 MB вграден L2 кеш) и 512 MB DDR2 RAM. Предната шина е с тактова честота 400 MHz. ОС е Windows XP Professional Edition със сервизен пакет 2. JVM е версия 1.5.0_06.

Бенчмаркът тества най-новите версии на следните XML парсери:

  • Xerces DOM 2.7.1, със и без отложено разширение на възел
  • Xerces SAX 2.7.1
  • Piccolo SAX 1.04
  • XPP3 1.1.3.4.O
  • VTD-XML 1.5, със и без повторно използване на буфера

За теста избрах голяма колекция от XML документи с различни размери и структурна сложност. В зависимост от размера на файла, тестовите документи са групирани в три категории. Малките файлове са с размер под 10 KB. Файловете със среден размер са между 10 KB и 1 MB. Файловете по-големи от 1 MB се считат за големи.

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 и Pull служи само като допълнителна отправна точка.

Пропускателна способност

Сравнение на латентността

Таблица 1. Малки файлове

Име / размер на файла VTD-XML (ms) Повторно използване на VTD-XML буфер (ms) SAX (ms) DOM (ms) DOM отложен (ms) Piccolo (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 файлове