【问题标题】:How to estimate memory need by XPathDocument for a specific xml file如何估计 XPathDocument 对特定 xml 文件的内存需求
【发布时间】:2010-12-30 01:48:54
【问题描述】:

有没有办法根据 xml 的文件大小来估计创建 XpathDocument 实例的内存需求?

XpathDocument xdoc = new XpathDocument(xmlfile);

如果内存下降到非常低的水平,是否有任何方法可以以编程方式停止创建 XpathDocument 的过程?

由于它将整个 xml 加载到内存中,因此如果 xml 太大,最好提前知道。我发现,当我用一个大的 xml 文件创建一个新的 XpathDocument 时,永远不会触发内存不足异常,但是该过程会慢到爬行,只有 5 Mb 的内存仍然可用,并且任务管理器报告它不是回应。当内存为 584 Mb 时,这发生在 266 Mb 的 xml 文件中。我能够在 18 年毫无问题地加载 150 Mb 文件。

加载 xml 后,我想使用 XpathNavigator 和 XpathNodeIterator 进行 xpath 查询。我正在使用 .net 2.0,xp sp3。

【问题讨论】:

    标签: c# xpathdocument


    【解决方案1】:

    简而言之,不,您不能,除非您在开始估算之前总是有类似的文件来收集静态数据。

    由于标签、属性、前缀和命名空间字符串是内部的,它在很大程度上取决于 XML 文件的结构,存储效率如何,与磁盘上的文件相比的比率也取决于使用的编码。

    通常,.NET 将任何字符串作为 UTF16 存储在内存中。因此,即使没有显着的结构开销(想象一个只有一个根标记和大量纯文本的 XML 文件),对于 UTF8 源文件(或者 ASCII 或任何其他 8-位编码)使用。所以字符串编码是等式的第一部分。

    另一件事是在内存中构建了一个数据结构,以允许有效地遍历文档。通常,节点是通过引用构建和链接在一起的。因此每个节点都会占用一定的内存;由于大多数非值数据都是引用,因此这里使用的内存也很大程度上取决于架构(64 位使用单个引用的内存是 32 位系统的两倍)。因此,如果您有一个非常复杂且数据很少的文档(例如,一大堆带有少量文本或属性值的不同标签),您的内存使用量将远高于原始文档大小,这也很大程度上取决于运行应用程序的架构。

    如果您有一个文件很少有很长的标签和属性名称,并且可能会大量使用默认命名空间,那么使用的内存也可能比磁盘上的文件低得多。

    因此,假设一个具有未知编码、合理数量的数据和复杂性的任意 XML 文件将很难得到可靠的估计。但是,如果您的 XML 文件在所提到的点上总是相似的,您可以创建一些统计数据来获得一个因素,该因素会为您的特定平台获得正确的比率。

    但是,请注意,在任务管理器中查看“可用内存”或谈论“非常低的内存级别”是非常模糊的量化。虚拟内存、缓存、后台应用程序和服务等将影响有效的原始内存可用性。因此,.NET 框架无法可靠地猜测它应该允许使用多少内存来保持单个进程的性能,甚至在安全地抛出 OutOfMemoryException 之前。因此,如果您遇到这些异常之一,您的应用程序通常会超出可能的恢复点,因此您不应尝试捕获和处理这些异常。

    【讨论】:

      【解决方案2】:

      您可以简单地检查文件大小,如果超过某个上限则退出。

      var xmlFileInfo = new FileInfo(xmlfile);
      var isTooBig = xmlFileInfo.Length > maximumSize
      

      这不是万无一失的,因为您无法猜测正确的最大尺寸是多少。

      【讨论】:

      • 我的问题转过来基本上是对于可用内存量的最大文件大小应该是多少。我希望做得比猜测更好。
      • @bill:如果可能的话,要找到那个神奇的价值并不容易。你读过 Eric Lippert 的精彩 article about out-of-memory errors 吗?它显示了这件事有多么复杂。再加上您无法控制 XPathDocument 的内部结构,这让您不得不猜测......
      • 我怀疑这并不容易。我能做的是建立一个 XPathDocument 使用的内存表,用于增加大小的文件并使用它。
      • @bill:阅读卢塞罗回答的最后一段,以及我提到的文章。找出你何时有足够的内存是最困难/不可能的问题,而不是找到你需要多少。
      【解决方案3】:

      是的,您可以使用 FileInfo 类来做到这一点。

      System.IO.FileInfo foo = new System.IO.FileInfo("<your file path as string>"); 
      long Size = foo.Length;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-28
        • 1970-01-01
        • 2013-08-08
        • 1970-01-01
        • 2011-04-03
        • 1970-01-01
        • 1970-01-01
        • 2012-02-22
        相关资源
        最近更新 更多