决定何时使用XmlDocument vs XmlReader

时间:2009-10-01 16:38:57

标签: c# xml-serialization xmldocument xmlreader

我正在优化自定义对象 - > XML序列化实用程序,它已经完成并正常工作,这不是问题。

它通过将文件加载到XmlDocument对象,然后以递归方式遍历所有子节点来工作。

我认为可能使用XmlReader而不是XmlDocument加载/解析整个事情会更快,所以我也实现了该版本。

算法完全相同,我使用包装类来抽象处理XmlNodeXmlReader的功能。例如,GetChildren方法会返回子XmlNode或子树XmlReader

所以我写了一个测试驱动程序来测试这两个版本,并使用一个非平凡的数据集(一个900kb的XML文件,大约有1,350个元素)。

但是,使用JetBrains dotTRACE,我发现XmlReader版本实际上比XmlDocument版本慢!当我迭代子节点时,XmlReader读取调用似乎有一些重要的处理。

所以我要说这一切:

XmlDocumentXmlReader有哪些优缺点?您应该在什么情况下使用?

我的猜测是,文件大小阈值XmlReader在性能上变得更经济,而且内存密集程度更低。但是,该阈值似乎超过1MB。

我每次都在调用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);
    }
}

该测试适用于单个级别的许多对象(即宽和浅) - 但我想知道当XML深入时,XmlReader的票价是多少。宽?即我正在处理的XML很像数据对象模型,1个父对象到许多子对象等:1..M..M..M

我之前也不知道我正在解析的XML的结构,所以我无法对其进行优化。

5 个答案:

答案 0 :(得分:68)

我一般都认为不是从最快的角度来看,而是从内存利用率的角度来看。对于我在其中使用过的使用场景(典型的企业集成),所有实现都足够快。

然而,在我失败的时候,有时甚至是惊人的,并没有考虑到我正在使用的XML的一般大小。如果你事先考虑一下,你可以省去一些悲伤。

XML加载到内存时往往会膨胀,至少使用像XmlDocumentXPathDocument这样的DOM读取器。像10:1这样的东西?确切的数量难以量化,但如果它在磁盘上为1MB,则内存为10MB或更多。

使用任何将整个文档整体加载到内存中的读取器(XmlDocument / XPathDocument)的进程可能会受到大对象堆碎片的影响,这最终会导致OutOfMemoryException s (即使有可用内存)导致服务/进程不可用。

  

由于大于85K的对象最终会出现在大型对象堆上,并且您使用DOM读取器进行了10:1大小的爆炸,您可以看到它在XML文档之前不需要太多从大对象堆中分配。

XmlDocument非常易于使用。它唯一的缺点是它将整个XML文档加载到内存中进行处理。它诱人的使用简单。

XmlReader是一个基于流的阅读器,因此可以保持您的进程内存利用率通常更平坦但更难以使用。

XPathDocument往往是一个更快,只读的XmlDocument版本,但仍然受到内存'膨胀'的困扰。

答案 1 :(得分:11)

XmlDocument是整个XML文档的内存中表示形式。因此,如果您的文档很大,那么它将比使用XmlReader读取它时消耗更多的内存。

这假设当您使用XmlReader时,您逐个读取并处理元素,然后丢弃它。如果您使用XmlReader并在内存中构建另一个中间结构,那么您就会遇到同样的问题,并且您的目的就是失败。

Google for“SAX versus DOM”可以阅读有关处理XML的两种模式之间差异的更多信息。

答案 2 :(得分:4)

另一个考虑因素是XMLReader可能更强大,可以处理不完美格式的XML。我最近创建了一个使用XML流的客户端,但该流没有在某些元素中包含的URI中正确转义特殊字符。 XMLDocument和XPathDocument完全拒绝加载XML,而使用XMLReader我能够从流中提取我需要的信息。

答案 3 :(得分:0)

有一个大小阈值,XmlDocument变慢,最终无法使用。但是阈值的实际值将取决于您的应用程序和XML内容,因此没有严格的规则。

如果您的XML文件可以包含大型列表(比如数万个元素),那么您肯定应该使用XmlReader。

答案 4 :(得分:0)

编码差异是因为混合了两种不同的测量值。 UTF-32每个字符需要4个字节,并且本质上比单字节数据慢。

如果你看一下大型(100K)元素测试,你会发现无论使用何种加载方法,每种情况下的时间增加约70mS。

这是一个(几乎)恒定的差异,特别是由每个字符开销引起的,

相关问题