|
01
02
03
04
05
06
07
08
09
10
11
|
<?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>... |
Существует соответствующий Java-объект Person для объекта Person в XML
..
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@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.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
@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
- SAX
- DOM
Были использованы реализации для JAXB, SAX и DOM. Затем был использован синтаксический анализ Woodstox STAX. Это можно было бы назвать в некоторых тестах JAXB.
Тесты проводились на моем ноутбуке Dell, двухъядерном процессоре Pentium с частотой 2,1 ГГц и Windows 7.
Тест 1 — Использование JAXB для демаршаллизации файла Java.
|
1
2
3
4
5
6
|
@Testpublic 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 для демаршалла Streamsource
Тест 2 аналогичен Тесту 1, за исключением того, что на этот раз объект Streamsource оборачивается вокруг объекта File. Объект Streamsource дает подсказку реализации JAXB для потоковой передачи файла.
|
1
2
3
4
5
6
7
|
@Testpublic 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 оборачивает экземпляр FileReader, который не вызывается JAXB.
|
1
2
3
4
5
6
7
8
9
|
@Testpublic 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.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@Testpublic 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-документа. Подход SAX включает в себя больше кода и больше сложности, чем любой подход JAXB. Разработчик должен принять участие в разборе документа.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
@Testpublic 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);} |
Тесты были выполнены 5 раз для 3 файлов, которые содержат коллекцию сущностей Person. Первый первый файл содержал 100 объектов лиц и был размером 5 КБ. Второй содержал 10 000 объектов и был размером 500 КБ, а третий содержал 250 000 объектов лица и был размером 15 Мег. Ни в одном из случаев не использовались XSD и не проводились проверки. Результаты приведены в таблицах результатов, в которых времена для разных прогонов разделены запятыми.
РЕЗУЛЬТАТЫ ТЕСТА
Сначала тесты выполнялись с использованием 32-битной JDK 1.6.26, и использовалась эталонная реализация для SAX, DOM и JAXB, поставляемая с JDK.
| Unmarshall Тип | 100 человек время (мс) | 10K человек время (мс) | 250K человек время (мс) |
| JAXB (по умолчанию) | 48,13, 5,4,4 | 78, 52, 47,50,50 | 1522, 1457, 1353, 1308, 131 |
| JAXB (StreamSource) | 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 |
| SAX | 4, 2, 1,1,1 | 29, 34, 23,26,26 | 704, 669, 605, 589 591 |
JDK 1.6.26 Тестовые комментарии
- Первый раз, когда происходит беспорядочный вызов, обычно самый длинный.
- Использование памяти для JAXB и SAX аналогично. Это около 2 мегабайт для файла с 10 000 человек и 36 — 38 мегабайт для 250 000 человек. Использование памяти DOM намного выше. Для файла на 10000 человек это 6 Мег, для файла на 250 000 человек это больше, чем 130 Мег.
- Время исполнения для чистого SAX лучше. В частности, для очень больших файлов.
Те же самые тесты были проведены снова, используя тот же JDK (1.6.26), но на этот раз была использована реализация синтаксического анализа StAX в Woodstox.
| Unmarshall Тип | 100 человек время (мс) | 10K человек время (мс) | 250K человек время (мс) |
| JAXB (по умолчанию) | 168,3,5,8,3 | 294, 43, 46, 43, 42 | 2055, 1354, 1328, 1319, 1319 |
| JAXB (StreamSource) | 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 |
| SAX | 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 парсинга используется.
- Время исполнения для чистого SAX по-прежнему самое лучшее. в частности
для больших файлов.
Те же самые тесты были проведены снова, но на этот раз я использовал JDK 1.7.02 и реализацию синтаксического анализа StAX в Woodstox.
| Unmarshall Тип | 100 человек время (мс) | 10000 человек время (мс) | 250 000 человек время (мс) |
| JAXB (по умолчанию) | 165,5, 3, 3,5 | 611,23, 24, 46, 28 | 578, 539, 511, 511, 519 |
| JAXB (StreamSource) | 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 |
| SAX | 7,2,2,1,1 | 169,15, 15, 19, 14 | 366, 364, 363, 360, 358 |
JDK 7 + комментарии к тесту Woodstox:
- Время выполнения JDK 7 в целом намного лучше. Есть некоторые аномалии — при первом анализе файла на 100 человек и файла на 10000 человек.
- Использование памяти немного выше. Для SAX и JAXB это 2 — 4 мегабайта для файла на 10000 человек и 45 — 49 мегабайт для файла на 250 000 человек. Для DOM это снова выше. 5 — 7,5 мегабайт для файла на 10000 человек и 136 — 143 мегабайт для файла на 250 000 человек
Примечание: WRT все тесты
- Для файла на 100 человек анализ памяти не проводился. Использование памяти было слишком маленьким, и поэтому в нем была бы бессмысленная информация.
- Первая инициализация контекста JAXB может занять до 0,5 секунды. Это не было включено в результаты теста, поскольку это заняло это время только в первый раз. После этого JVM очень быстро инициализирует контекст (не более 5 мс). Если вы заметили такое поведение в используемой вами реализации JAXB, попробуйте выполнить инициализацию при запуске.
- Эти тесты представляют собой очень простой XML-файл. В действительности было бы больше типов объектов и более сложный XML. Тем не менее, эти тесты должны по-прежнему служить руководством.
Выводы:
- Время работы чистого SAX немного лучше, чем JAXB, но только для очень больших файлов. Если вы не используете очень большие файлы, разница в производительности не стоит беспокоиться. Преимущества модели прогамминга JAXB выигрывают над сложностью модели программирования SAX. Не забывайте, JAXB также предоставляет случайные обвинения, как это делает DOM. SAX не обеспечивает этого.
- Времена производительности выглядят намного лучше с Woodstox, если используется JAXB / StAX.
- Время исполнения с 64-битным JDK 7 выглядит намного лучше. Использование памяти выглядит немного выше.
Ссылка: JAXB, SAX, DOM Performance от нашего партнера JCG Алекса Стейвли в техническом блоге Дублина .
Статьи по Теме :