<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persons><person><id>person0</id><name>name0</name></person><person><id>person1</id><name>name1</name></person>
...
XML中的Person實體有一個對應的Person Java對象
..
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"id","name"
})
public class Person {private String id;private String name;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String value) {this.name = value;}
}
和一個PersonList對象代表一個Persons集合。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "persons")
public class PersonList {@XmlElement(name="person")private List<person> personList = new ArrayList<person>();public List<person> getPersons() {return personList;}public void setPersons(List<person> persons) {this.personList = persons;}
}
研究的方法是:
- 各種口味的JAXB
- 薩克斯
- DOM
使用了JAXB,SAX和DOM的實現。 然后使用Woodstox STAX解析。 在某些JAXB解組測試中會調用此方法。
測試是在運行Windows 7的戴爾筆記本電腦,2.1 GHz奔騰雙核CPU上進行的。
測試1 –使用JAXB解組Java文件。
@Test
public void testUnMarshallUsingJAXB() throws Exception {JAXBContext jc = JAXBContext.newInstance(PersonList.class);Unmarshaller unmarshaller = jc.createUnmarshaller();PersonList obj = (PersonList)unmarshaller.unmarshal(new File(filename));
}
測試1說明了JAXB的編程模型有多簡單。 從XML文件到Java對象非常容易。 無需參與編組和解析的精妙細節。
測試2 –使用JAXB解組流源
測試2與測試1類似,不同之處在于,這次流源對象包裝在文件對象周圍。 Streamsource對象向JAXB實現提供提示以流式傳輸文件。
@Test
public void testUnMarshallUsingJAXBStreamSource() throws Exception {JAXBContext jc = JAXBContext.newInstance(PersonList.class);Unmarshaller unmarshaller = jc.createUnmarshaller();StreamSource source = new StreamSource(new File(filename));PersonList obj = (PersonList)unmarshaller.unmarshal(source);
}
測試3 –使用JAXB解組StAX XMLStreamReader
再次類似于測試1,除了這次XMLStreamReader實例包裝了由JAXB編組的FileReader實例。
@Test
public void testUnMarshallingWithStAX() throws Exception {FileReader fr = new FileReader(filename);JAXBContext jc = JAXBContext.newInstance(PersonList.class);Unmarshaller unmarshaller = jc.createUnmarshaller();XMLInputFactory xmlif = XMLInputFactory.newInstance();XMLStreamReader xmler = xmlif.createXMLStreamReader(fr);PersonList obj = (PersonList)unmarshaller.unmarshal(xmler);
}
測試4 –僅使用DOM
該測試不使用JAXB,而是僅使用JAXP DOM方法。 這意味著比任何JAXB方法都需要更多的代碼。
@Test
public void testParsingWithDom() throws Exception {DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = domFactory.newDocumentBuilder();Document doc = builder.parse(filename);List personsAsList = new ArrayList();NodeList persons = doc.getElementsByTagName("persons");for (int i = 0; i <persons.getLength(); i++) {Element person = (Element)persons.item(i);NodeList children = (NodeList)person.getChildNodes();Person newperson = new Person();for (int j = 0; j < children.getLength(); j++){Node child = children.item(i);if (child.getNodeName().equalsIgnoreCase("id")) {newperson.setId(child.getNodeValue());} else if (child.getNodeName().equalsIgnoreCase("name")) {newperson.setName(child.getNodeValue());}}personsAsList.add(newperson);}
}
測試5 –僅使用SAX測試5不使用JAXB,而使用SAX來解析XML文檔。 與任何JAXB方法相比,SAX方法涉及更多的代碼和更多的復雜性。 開發人員必須參與文檔的解析。
@Test
public void testParsingWithSAX() throws Exception {SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser saxParser = factory.newSAXParser();final List<person> persons = new ArrayList<person>();DefaultHandler handler = new DefaultHandler() {boolean bpersonId = false;boolean bpersonName = false;public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException {if (qName.equalsIgnoreCase("id")) {bpersonId = true;Person person = new Person();persons.add(person);} else if (qName.equalsIgnoreCase("name")) {bpersonName = true;}}public void endElement(String uri, String localName, String qName) throws SAXException {}public void characters(char ch[], int start, int length) throws SAXException {if (bpersonId) {String personID = new String(ch, start, length);bpersonId = false;Person person = persons.get(persons.size() - 1);person.setId(personID);} else if (bpersonName) {String name = new String(ch, start, length);bpersonName = false;Person person = persons.get(persons.size() - 1);person.setName(name);}}};saxParser.parse(filename, handler);
}
對于包含Person實體集合的3個文件,該測試運行了5次。 第一個文件包含100個Person實體,大小為5K。 第二個包含10,000個實體,大小為500K,第三個包含250,000個Person實體,大小為15 Meg。 在任何情況下都不會使用任何XSD或進行任何驗證。 結果在結果表中給出,其中不同運行時間用逗號分隔。
試驗結果
首先使用32位JDK 1.6.26運行測試,并使用JDK附帶的SAX,DOM和JAXB的參考實現。
解組類型 | 100人次(毫秒) | 10K人次(毫秒) | 25萬人次(毫秒) |
JAXB(默認) | 48,13,5,4,4 | 78,52,47,50,50 | 1522、1457、1353、1308、1317 |
JAXB(流源) | 11,6,3,3,2 | 44,44,48,45,43 | 1191、1364、1144、1142、1136 |
JAXB(StAX) | 18,2,1,1,1 | 111、136、89、91、92 | 2693、3058、2495、2472、2481 |
DOM | 16,2,2,2,2 | 89,50,55,53,50 | 1992、2198、1845、1776、1773 |
薩克斯 | 4,2,1,1,1 | 29,34,23,26,26 | 704、669、605、589,591 |
JDK 1.6.26測試注釋
- 通常,第一次進行編組的時間最長。
- JAXB和SAX的內存使用情況相似。 10,000個人的檔案約為2 Meg,而250,000的檔案是36 – 38 Meg檔案。 DOM內存使用率更高。 對于10,000個人檔案,它是6 Meg,對于250,000個人檔案,它是大于130 Meg。
- 純SAX的性能更好。 特別是對于非常大的文件。
使用相同的JDK(1.6.26)再次運行完全相同的測試,但是這次使用了StAX解析的Woodstox實現。
解組類型 | 100人次(毫秒) | 10K人次(毫秒) | 25萬人次(毫秒) |
JAXB(默認) | 168,3,5,8,3 | 294、43、46、43、42 | 2055、1354、1328、1319、1319 |
JAXB(流源) | 11,3,3,3,4 | 43,42,47,44,42 | 1147、1149、1176、1173、1159 |
JAXB(StAX) | 30,0,1,1,0 | 67,37,40,37,37 | 1301、1236、1223、1336、1297 |
DOM | 103,1,1,1,2 | 136,52,49,49,50 | 1882、1883、1821、1835、1822 |
薩克斯 | 4,2,2,1,1 | 31,25,25,38,25 | 613、609、607、595、613 |
JDK 1.6.26 + Woodstox測試注釋
- 同樣,第一次進行編組通常會成比例地變長。
- 同樣,SAX和JAXB的內存使用情況非常相似。 兩者都好得多
比DOM。 結果與測試1非常相似。
- JAXB(StAX)進近時間已大大縮短。 這是由于
正在使用StAX解析的Woodstox實現。
- 純SAX的性能時間仍然是最好的。 尤其
用于大文件。
再次運行完全相同的測試,但是這次我使用了JDK 1.7.02和StAX解析的Woodstox實現。
解組類型 | 100人次(毫秒) | 10,000人次(毫秒) | 250,000人次(毫秒) |
JAXB(默認) | 165,5,3,3,5 | 611,23,24,46,28 | 578、539、511、511、519 |
JAXB(流源) | 13,4,3,4,3 | 43,24,21,26,22 | 678、520、509、504、627 |
JAXB(StAX) | 21,1,0,0,0 | 300,69,20,16,16 | 637、487、422、435、458 |
DOM | 22,2,2,2,2 | 420,25,24,23,24 | 1304、807、867、747、1189 |
薩克斯 | 7,2,2,1,1 | 169,15,15,19,14 | 366、364、363、360、358 |
JDK 7 + Woodstox測試注釋:
- 總體而言,JDK 7的性能要好得多。 有一些異常-第一次解析100個人和10,000個人檔案。
- 內存使用量略高。 對于SAX和JAXB,10,000人檔案為2 – 4 Meg,對于250,000人檔案為45 – 49 Meg。 對于DOM,它再次更高。 10,000人的檔案5 – 7.5 Meg,250,000人的檔案136 – 143 Meg。
注意:WRT所有測試
- 沒有對100人文件進行內存分析。 內存使用量太小,因此將沒有意義的信息。
- 首次初始化JAXB上下文最多需要0.5秒。 這不包括在測試結果中,因為這只是第一次。 之后,JVM會非常快地初始化上下文(始終小于5毫秒)。 如果您在使用任何JAXB實現時都注意到此行為,請考慮在啟動時進行初始化。
- 這些測試是一個非常簡單的XML文件。 實際上,將會有更多的對象類型和更復雜的XML。 但是,這些測試仍應提供指導。
結論:
- 純SAX的性能時間略好于JAXB,但僅適用于非常大的文件。 除非使用的文件非常大,否則性能差異不值得擔心。 JAXB的編程模型優勢克服了SAX編程模型的復雜性。 別忘了JAXB也像DOM一樣提供隨機訪問。 SAX不提供此功能。
- 如果使用JAXB / StAX,則使用Woodstox的性能時間看起來要好得多。
- 使用64位JDK 7的性能看起來要好得多。 內存使用情況看起來略高。
參考:來自都柏林技術博客的 JCG合作伙伴 Alex Staveley的JAXB,SAX,DOM性能 。
相關文章 :
- 使用JAXB從XSD生成XML
- 將對象映射到多個XML模式–天氣示例
- 使用Spring MVC開發Restful Web服務
- 具有簡單框架教程的Android XML綁定
- 使用XML Pull增強Android XML解析
翻譯自: https://www.javacodegeeks.com/2011/12/jaxb-sax-dom-performance.html