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


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

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

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

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

поэтому я написал тестовый драйвер для тестирования обеих версий и использования нетривиального набора данных (XML-файл 900kb с примерно 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 60

5 ответов:

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

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

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

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

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

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

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

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

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

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

Google для "саксофон против дома " подробнее о разнице между двумя моделями обработки XML.

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

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

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

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

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

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