2009-10-01 15 views
60

Estoy optimizando un objeto personalizado -> utilidad de serialización XML, y todo está hecho y funcionando, y ese no es el problema.Decidir cuándo usar XmlDocument contra XmlReader

Funcionó al cargar un archivo en un objeto XmlDocument, y luego recursivamente a través de todos los nodos secundarios.

que pensé que tal vez usando XmlReader en lugar de tener XmlDocument carga/analizar toda la cosa sería más rápido, por lo que esa versión implementado también.

Los algoritmos son exactamente lo mismo, yo uso una clase contenedora para abstraer la funcionalidad de tratar con un XmlNode frente a un XmlReader. Por ejemplo, los métodos GetChildren dan como resultado un niño XmlNode o un SubTree XmlReader.

Así que escribí un controlador de prueba para probar ambas versiones, y el uso de un conjunto de datos no triviales (un archivo XML de 900kb con alrededor de 1.350 elementos).

Sin embargo, usando JetBrains dotTRACE, veo que la versión XmlReader es en realidad más lenta que la versión XmlDocument! Parece que hay un procesamiento significativo involucrado en las llamadas de lectura XmlReader cuando estoy iterando sobre nodos secundarios.

Así que todo lo que dicen que hacen esta:

¿Cuáles son las ventajas/desventajas de XmlDocument y XmlReader, y en qué circunstancias debe usted utilizar cualquiera?

Supongo que hay un umbral de tamaño de archivo en el que XmlReader se vuelve más económico en rendimiento, y requiere menos memoria. Sin embargo, ese umbral parece estar por encima de 1MB.

Voy a llamar cada vez que ReadSubTree para procesar nodos hijos:

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); 
    } 
} 

Esa prueba se aplica a una gran cantidad de objetos en un único nivel (es decir, amplia & superficial) - pero me pregunto qué tan bien cuando XmlReader tarifas el XML es profundo & ancho? Es decir. el XML que estoy tratando es muy similar a un modelo de objeto de datos, 1 objeto principal a muchos objetos secundarios, etc. 1..M..M..M

Tampoco sé de antemano la estructura del XML que estoy analizando, entonces puedo optimizar para ello.

+1

Siempre me he preguntado por qué había un XmlDocument y un XmlReader ... –

+0

En realidad, hay otra opción para XMLDocument y XMLReader. Ahora puede usar LINQ to XML pero en realidad XMLReader es más eficiente en la mayoría de los sentidos. – Tarik

+2

Espera. Su método 'GetChildren' devuelve' XmlReader' ¿Quiere decir que llama a 'XmlReader.Create()' cada vez que procesa un nodo secundario? –

Respuesta

63

generalmente He mirado en que no desde una perspectiva más rápido, sino más bien desde una perspectiva de utilizaciónmemoria. Todas las implementaciones han sido lo suficientemente rápidas para los escenarios de uso en los que los he usado (integración empresarial típica).

Sin embargo, donde me he caído, y algunas veces de manera espectacular, no estoy teniendo en cuenta el tamaño general del XML con el que estoy trabajando. Si lo piensas al principio puedes ahorrarte algo de dolor.

XML tiende a hincharse cuando se carga en la memoria, al menos con un lector DOM como XmlDocument o XPathDocument. Algo así como 10: 1? La cantidad exacta es difícil de cuantificar, pero si es 1 MB en el disco, será de 10 MB en la memoria, o más, por ejemplo.

Un proceso usando cualquier lector que se carga todo el documento en la memoria en su totalidad (XmlDocument/XPathDocument) pueden sufrir de gran fragmentación objeto montón, lo que finalmente puede conducir a OutOfMemoryException s (incluso con la memoria disponible) que resulta en un servicio no disponible /proceso.

Dado que los objetos con un tamaño superior a 85K terminan en el gran montón de objetos, y tiene una explosión de tamaño 10: 1 con un lector DOM, puede ver que no tarda mucho antes Los documentos XML se asignan desde el montón de objetos grandes.

XmlDocument es muy fácil de usar. Su único inconveniente real es que carga todo el documento XML en la memoria para procesar. Es seductoramente simple de usar.

XmlReader es un lector basado en flujo, por lo que mantendrá la utilización de la memoria de proceso generalmente más plana pero es más difícil de usar.

XPathDocument tiende a ser una versión más rápida, de solo lectura de XmlDocument, pero todavía sufre de 'hinchazón' de memoria.

+4

Cargar documentos XML, sin importar cuán grandes, en la memoria NO causa objetos grandes. ¡Sin embargo, mantener el XML como una cadena! Es el tamaño de los objetos individuales lo que importa con respecto a la capacidad del GC para desfragmentar la memoria, pero el tamaño total del gráfico del objeto es lo que importa con respecto al uso de la memoria. –

+1

FWIW Acabo de hacer un punto de referencia entre XDocument, XMLReader y XmlDocument. Para hacer rutas similares tomaron 0.004, 0.001 y 0.692 segundos respectivamente. – micahhoover

0

Hay un umbral de tamaño en el que XmlDocument se vuelve más lento y, finalmente, inutilizable. Pero el valor real del umbral dependerá de su aplicación y del contenido XML, por lo que no existen reglas estrictas.

Si su archivo XML puede contener listas grandes (digamos decenas de miles de elementos), definitivamente debe usar XmlReader.

9

XmlDocument es una representación en memoria de todo el documento XML. Por lo tanto, si su documento es grande, consumirá mucha más memoria que si lo hubiera leído usando XmlReader.

Esto supone que cuando usa XmlReader lee y procesa los elementos uno por uno y luego lo descarta.Si usa XmlReader y construye otra estructura intermedia en la memoria, entonces tiene el mismo problema, y ​​está derrotando el propósito de la misma.

Google para "SAX versus DOM" para leer más sobre la diferencia entre los dos modelos de procesamiento de XML.

+1

Lo molesto es que no hay absolutamente ninguna indicación de dónde (estadio) un documento se convierte en "grande" y XmlReader comienza a producir cualquier beneficio de tamaño considerable. ¿Es 1KB, 1MB o incluso mucho más? Estoy seguro de que la respuesta es "depende", pero sin una pista en absoluto, tenemos que determinar estas cosas de forma experimental caso por caso, excepto en los casos en que sea capaz de manejar datos arbitrariamente grandes. (entonces XmlReader es la opción más clara). –

0

La diferencia de codificación se debe a que se mezclan dos medidas diferentes. UTF-32 requiere 4 bytes por carácter, y es intrínsecamente más lento que los datos de un solo byte.

Si observa la prueba de elementos grandes (100K), verá que el tiempo aumenta en aproximadamente 70mS para cada caso, independientemente del método de carga utilizado.

Este es un (casi) diferencia constante causados ​​específicamente por la sobrecarga por carácter,

4

Otra consideración es que XMLReader podría ser más robusto para el manejo de XML menos-que-perfectamente-formado. Recientemente, creé un cliente que consumía una secuencia XML, pero la secuencia no tenía los caracteres especiales escapados correctamente en los URI contenidos en algunos de los elementos. XMLDocument y XPathDocument se negaron a cargar el XML, mientras que con XMLReader pude extraer la información que necesitaba de la transmisión.

Cuestiones relacionadas