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