【问题标题】:How to optimize operations with large xml files (Download/Parsing)如何优化大型 xml 文件的操作(下载/解析)
【发布时间】:2013-07-25 22:02:39
【问题描述】:
我有一个应用程序需要通过 http 大量 (>10k) 下载大型 xml 文件 (8-10MB),使用一个 xpath 表达式在其中获取一些内容。
我想知道如何优化这个过程。这些 xml 文件将直接进入大对象堆。
我在考虑三个选项:
- 整体优化:使用单独的IO线程池下载xml文件
- 使用流来读取带有 xml 文件的 Web 响应,而不是读入将转到 LOH 的字符串(不确定是否可能以及如何做到这一点)
- 使用正则表达式从 XML 中检索内容,因为 XPath 非常简单,我不需要完整的 DOM 支持。
还有其他选择吗?
【问题讨论】:
标签:
c#
xml
regex
garbage-collection
large-object-heap
【解决方案1】:
有很多优化选项,具体取决于您要最大化的内容。
如果您的处理速度比下载速度快(并且很难想象您的基于 XPath 的搜索会很慢),那么您的限制因素将是下载速度。您可以使用异步请求一次下载多个文件,但如果所有文件都来自同一台服务器,那么少量的并发下载不太可能给您带来任何性能提升。
您可以在下载时从流中创建一个XmlReader,然后(我认为,虽然我不确定)针对流运行您的 XPath 表达式。但这并没有真正给你带来任何好处。
我认为您不必要地担心大型对象堆。如果您一次下载和处理一个文件,则每个字符串都将进入 LOH,得到处理,然后被收集。是的,可能将您的大型对象堆碎片化,但如果文件都在 8 到 10 MB 范围内,那么实际上您不太可能遇到问题。必须对文件进行病态排列。
而且您实际上不必下载到字符串。您可以预先分配 20 MB 的缓冲区,然后下载到该缓冲区。然后在它周围包裹一个MemoryStream,在该内存流上创建一个XmlReader,等等。所以你的LOH根本不会碎片化,因为你只是重新使用那个20 MB的缓冲区。不过,除非万不得已,否则我真的不会走这条路。
如果我分配了这项任务,我会以最简单的方式完成。限制因素将是下载速度,所以我会集中精力进行优化。我一点也不担心潜在的 LOH 碎片,但请把备用解决方案放在我的后兜里,以防万一出现问题。
您如何处理这实际上取决于 XPath 搜索的速度。如果搜索一个 10 MB 的 XML 文件需要几毫秒甚至几秒钟的时间,那么担心优化搜索根本没有意义:下载时间将使搜索时间相形见绌。相反,我会看看我是否可以获得两个或四个并发下载,将每个字符串结果放入BlockingCollection,然后让消费者线程读取该队列并运行搜索。该消费者线程可能会花费大量时间空闲,等待下一个文件下来。
简而言之:让它发挥作用,然后让它快速发挥作用。