滥用XmlReader ReadSubtree()
我需要解析一个xml文件,该文件实际上是一个非常大的树结构的图像,因此我正在使用XmlReader类"即时"填充树。每个节点仅通过ReadSubtree()函数传递其期望从其父节点获得的xml块。这样做的好处是,不必担心节点何时耗尽了所有子节点。但是现在我想知道这是否真的是一个好主意,因为可能有成千上万个节点,并且在读取.NET源文件时,我发现每次ReadSubtree调用都会创建几个(可能还有更多)新对象,并没有为可重复使用的对象进行缓存(我见过)。
也许不认为ReadSubtree()被大量使用,或者也许我只是担心什么而已,我只需要在解析文件后调用GC.Collect()即可。
希望有人能对此有所启发。
提前致谢。
更新:
感谢我们提供的精妙而有见地的答案。
我对.NET源代码进行了更深入的研究,发现它比我最初想象的要复杂。我终于放弃了在这种情况下调用此函数的想法。正如Stefan所指出的那样,xml读取器永远不会传递给外部人员,而且我可以信任解析xml流的代码(由我自己编写),因此我宁愿强制每个节点负责它们的数据量。从流中窃取,而不是使用不太精简的ReadSubtree()函数仅保存几行代码。
解决方案
ReadSubTree()为我们提供一个包装原始XmlReader的XmlReader。对消费者来说,这本新的读者似乎是一个完整的文档。如果我们传递子树的代码认为它正在获取独立的xml文档,那么这可能很重要。例如,新Reader的Depth属性从0开始。它是一个非常薄的包装器,因此,与直接使用原始XmlReader相比,我们将不会使用更多的资源。在我们给出的示例中,它是很可能我们并没有真正从子树阅读器中受益匪浅。
在情况下,最大的优势是子树读取器不会意外地读取子树。由于子树读取器不是很昂贵,因此安全性可能就足够了,尽管当我们需要子树看起来像文档或者我们不信任代码仅读取其自己的子树时,它通常会更有用。
如Will所述,我们永远不需要调用GC.Collect()。它永远不会提高性能。
假设所有对象都是在普通托管堆上创建的,而不是在大对象堆(即小于85k)上创建的,那么这里确实应该没有问题,这正是GC旨在解决的问题。
我建议不要在过程结束时调用GC.Collect,因为在几乎所有情况下,允许GC自行安排集合的调度都可以使其以最佳方式工作(有关详细信息,请参阅此博客文章)。 GC的解释,这比我能解释的要好得多。