决定何时使用XmlDocument与XmlReader

我正在优化自定义对象 – > XML序列化实用程序,这一切都已经完成并且工作,这不是问题。

它通过加载一个文件到一个XmlDocument对象,然后recursion遍历所有的子节点。

我想,也许使用XmlReader而不是有XmlDocument加载/parsing整个事情会更快,所以我也实现了该版本。

algorithm是完全一样的,我使用包装类来抽象处理XmlNodeXmlReader 。 例如, GetChildren方法的yield返回一个子XmlNode或一个SubTree XmlReader

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

但是,使用JetBrains的dotTRACE,我看到XmlReader版本实际上比XmlDocument版本更慢! 当我遍历子节点时,似乎有一些重要的处理涉及XmlReader读取调用。

所以我就这么说:

XmlDocumentXmlReader的优点/缺点是什么,在什么情况下你应该使用?

我的猜测是有一个文件大小的阈值, XmlReader在性能上变得更经济,以及更less的内存密集。 不过,这个门槛似乎高于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); } } 

该testing适用于单个级别(即宽和浅)的许多对象 – 但我不知道XmlReader在XML深度和广度上的performance如何? 即我正在处理的XML非常像一个数据对象模型,许多子对象的父对象1: 1..M..M..M

我也不知道我正在parsing的XML的结构,所以我不能优化它。

我一般不是从最快的angular度来看 ,而是从内存利用的angular度来看。 所有的实现都已经足够快,以适应我使用它们的典型企业集成的情况。

但是,在我堕落的地方,有时甚至是令人惊叹的地方,并没有考虑到我正在使用的XML的大小。 如果你在前面考虑一下,你可以救自己一些悲伤。

当XML加载到内存时,XML往往会膨胀,至less使用XmlDocumentXPathDocument等DOM阅读器。 像10:1? 确切的数量是难以量化的,但是如果它在磁盘上是1MB,则在内存中将是10MB或更多。

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

由于大小超过85K的对象最终放在大对象堆中,而且DOM读取器的大小是10:1,所以您可以看到,在分配XML文档之前,大对象堆。

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

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

XPathDocument往往是一个更快,只读的XmlDocument版本,但仍然遭受内存的“膨胀”。

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

这是假设当你使用XmlReader你读取和处理的元素一个接一个,然后丢弃它。 如果你使用XmlReader并在内存中构造另一个中间结构,那么你也有同样的问题,并且你正在破坏它的目的。

Google针对“ SAX与DOM ”来详细介绍这两种处理XML模型的区别。

另一个考虑是XMLReader对于处理不完全形成的XML可能更加健壮。 我最近创build了一个客户端,它使用了一个XMLstream,但是这个stream没有在包含在一些元素中的URI中正确地转义特殊字符。 XMLDocument和XPathDocument拒绝加载XML,而使用XMLReader我能够从stream中提取所需的信息。

有一个大小阈值XmlDocument变得更慢,并最终无法使用。 但是阈值的实际值取决于您的应用程序和XML内容,所以没有硬性规定。

如果你的XML文件可以包含大的列表(比如说成千上万的元素),那么你一定要使用XmlReader。

编码差异是因为两个不同的测量值被混合在一起。 UTF-32每个字符需要4个字节,固有地比单字节数据慢。

如果你看一下大的(100K)unit testing,你会发现无论使用哪种加载方法,每种情况下的时间增加了大约70mS。

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