Решение о том, когда использовать XmlDocument vs XmlReader

Я оптимизирую утилиту customization → XML serialization, и все это сделано и работает, и это не проблема.

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

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

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

Итак, я написал тестовый драйвер для тестирования обеих версий и использовал нетривиальный набор данных (файл размером 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, который я разбираю, поэтому я не могу ее оптимизировать.

Ответ 1

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

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

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