Решение о том, когда использовать XmlDocument против XmlReader - PullRequest
61 голосов
/ 01 октября 2009

Я оптимизирую пользовательский объект -> утилиту сериализации XML, и все это сделано и работает, и это не проблема.

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

Я подумал, что, возможно, использование XmlReader вместо XmlDocument загрузки / анализа всего этого будет быстрее, поэтому я реализовал и эту версию.

Алгоритмы точно такие же, я использую класс-обертку, чтобы абстрагировать функциональность работы с XmlNode против XmlReader. Например, выход метода GetChildren возвращает либо дочерний элемент XmlNode, либо поддерево XmlReader.

.

Итак, я написал тестовый драйвер для тестирования обеих версий и использовал нетривиальный набор данных (XML-файл объемом 900 КБ, содержащий около 1350 элементов).

Однако, используя JetBrains dotTRACE, я вижу, что версия XmlReader на самом деле медленнее, чем версия XmlDocument! Кажется, что во время итерации по дочерним узлам XmlReader происходит некоторая значительная обработка.

Итак, я говорю все это, чтобы спросить:

Каковы преимущества / недостатки XmlDocument и XmlReader, и при каких обстоятельствах вы должны их использовать?

Я предполагаю, что существует порог размера файла, при котором XmlReader становится более экономичным по производительности, а также менее требовательным к памяти. Тем не менее этот порог превышает 1 МБ.

Я каждый раз вызываю ReadSubTree для обработки дочерних узлов:

public override IEnumerable<IXmlSourceProvider> GetChildren ()
{
    XmlReader xr = myXmlSource.ReadSubtree ();
    // skip past the current element
    xr.Read ();

    while (xr.Read ())
    {
        if (xr.NodeType != XmlNodeType.Element) continue;
        yield return new XmlReaderXmlSourceProvider (xr);
    }
}

Этот тест применим ко многим объектам на одном уровне (то есть, широкий и неглубокий) - но мне интересно, насколько хорошо XmlReader стоит, когда XML глубокий и широкий? То есть XML, с которым я имею дело, очень похож на модель объекта данных, 1 родительский объект для многих дочерних объектов и т. д .: 1..M..M..M

Я также не знаю заранее структуру XML-файла, который я анализирую, поэтому я не могу оптимизировать его.

Ответы [ 5 ]

68 голосов
/ 02 октября 2009

Я вообще смотрел на это не с самой быстрой перспективы , а скорее с использования памяти перспективы. Все реализации были достаточно быстрыми для сценариев использования, в которых я их использовал (типичная корпоративная интеграция).

Однако там, где я упал, а иногда и впечатляюще, не учитывается общий размер XML, с которым я работаю. Если вы думаете об этом заранее, вы можете спасти себя от горя.

XML имеет тенденцию увеличиваться в размерах при загрузке в память, по крайней мере, с помощью считывателя DOM, например XmlDocument или XPathDocument. Что-то вроде 10: 1? Точное количество трудно определить количественно, но если оно составляет 1 МБ на диске, то оно будет 10 МБ в памяти или более, например.

Процесс, использующий любое устройство чтения, которое загружает весь документ в память целиком (XmlDocument / XPathDocument), может пострадать от фрагментации кучи больших объектов, что в конечном итоге может привести к OutOfMemoryException с (даже при наличии доступной памяти) в результате чего недоступен сервис / процесс.

Поскольку объекты размером более 85 КБ попадают в кучу больших объектов, и вы получили взрыв размером 10: 1 с помощью DOM-ридера, вы можете видеть, что это не займет много времени, прежде чем ваши XML-документы выделяется из кучи большого объекта.

XmlDocument очень прост в использовании. Его единственный реальный недостаток заключается в том, что он загружает весь XML-документ в память для обработки. Соблазнительно прост в использовании.

XmlReader - потоковое считывающее устройство, поэтому использование памяти вашего процесса в целом будет более плоским, но более сложным в использовании.

XPathDocument имеет тенденцию быть более быстрой версией XmlDocument, предназначенной только для чтения, но все еще страдает от "раздувания" памяти.

11 голосов
/ 02 октября 2009

XmlDocument является представлением в памяти всего документа XML. Поэтому, если ваш документ большой, он будет занимать гораздо больше памяти, чем если бы вы читали его с помощью XmlReader.

Это предполагает, что когда вы используете XmlReader, вы читаете и обрабатываете элементы один за другим, а затем отбрасываете его. Если вы используете XmlReader и создаете другую промежуточную структуру в памяти, у вас возникает та же проблема, и вы побеждаете ее цель.

Google для " SAX против DOM ", чтобы узнать больше о разнице между двумя моделями обработки XML.

4 голосов
/ 13 апреля 2015

Другое соображение заключается в том, что XMLReader может быть более надежным для обработки XML, который сформирован не полностью. Недавно я создал клиента, который использовал поток XML, но в этом потоке не было специальных символов, экранированных правильно в URI, содержащихся в некоторых элементах. XMLDocument и XPathDocument вообще отказались загружать XML, тогда как с помощью XMLReader я смог извлечь нужную информацию из потока.

0 голосов
/ 11 ноября 2012

Разница в кодировке заключается в том, что смешиваются два разных измерения. UTF-32 требует 4 байта на символ и по своей природе медленнее, чем однобайтовые данные.

Если вы посмотрите на тест большого элемента (100 КБ), вы увидите, что время увеличивается примерно на 70 мс для каждого случая, независимо от используемого метода загрузки.

Это (почти) постоянная разница, вызванная определенными накладными расходами на символ,

0 голосов
/ 01 октября 2009

Существует порог размера, при котором XmlDocument становится медленнее и, в конечном итоге, становится непригодным для использования. Но фактическое значение порога будет зависеть от вашего приложения и содержимого XML, поэтому жестких и быстрых правил не существует.

Если ваш XML-файл может содержать большие списки (скажем, десятки тысяч элементов), вам определенно следует использовать XmlReader.

...