Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否存在任何不使用';是否在解析时加载整个文件?_C#_Xml_Dom - Fatal编程技术网

C# 是否存在任何不使用';是否在解析时加载整个文件?

C# 是否存在任何不使用';是否在解析时加载整个文件?,c#,xml,dom,C#,Xml,Dom,我有一些比可用内存大的XML文件,还有一个很大的(!)代码库,它假设可以使用DOM结构对该文件进行操作。然而,一些用户报告了大输入大小的OutOfMemoryException;而且XML比32位处理器上可用的地址空间大 是否有一个DOM实现可以处理这种情况,并且只在必要时“水合物”子对象,以便对大量XML文件实现合理的内存使用?这不是一个最佳解决方案,但在过去,我将XML文件读入字符串,并使用正则表达式将部分分解为它们自己的DOM对象 也许您也可以使用XPath?(https://develo

我有一些比可用内存大的XML文件,还有一个很大的(!)代码库,它假设可以使用DOM结构对该文件进行操作。然而,一些用户报告了大输入大小的OutOfMemoryException;而且XML比32位处理器上可用的地址空间大


是否有一个DOM实现可以处理这种情况,并且只在必要时“水合物”子对象,以便对大量XML文件实现合理的内存使用?

这不是一个最佳解决方案,但在过去,我将XML文件读入字符串,并使用正则表达式将部分分解为它们自己的DOM对象

也许您也可以使用XPath?(https://developer.mozilla.org/en-US/docs/Using_XPath)

微软XmlTeam的一项研究表明,他们可以从linq2xml中获益,但是可以流式传输文件,而不是在整个过程中加载。在经历了许多死路一条之后,当我从数据库转储读取>10GB xml文件时,这就是解决方案。

DOM对象模型依赖于将所有数据加载到内存的事实。即使您会发现一个实现延迟加载延迟的东西,但如果domapi用户遍历整个DOM树,您仍然会耗尽内存

实际上,在执行
XMemorySavingXDocument
.Load(“big.xml”)`时可以节省内存,但第一个XPath或LINQ查询仍然会导致OutOfMemoryException。如果任何查询确实遍历完整的DOM树,则这是正确的。如果您能确保这种情况永远不会发生,那么您就可以摆脱这种懒惰的DOM树

我不知道有任何这样的实施,但我怀疑它是否会对你的情况有所帮助。正如您所说的,大量domapi用户将遍历DOM树,接触所有节点,使用这种解决方案仅几毫秒后就会出现OutOfMemoryException

XMLDOM对象模型将XML文件“解压”为内存中的表示形式,该表示形式消耗的内存约为原始文件的7倍(x64)。对于32位,它仍然是大约3.5倍

XMLDOM模型如此臃肿的原因是每个DOM节点都知道它的子节点、父节点和属性。这是每个DOM节点的对象引用,这会花费您很多钱

托管类对象每个实例至少消耗12/24字节。由于每个节点指针都会在总内存消耗中再添加4/8字节(x86、x64),因此使用一个大xml文件时,内存很快就会耗尽。有关.NET对象大小的更多信息,请参见此

由于DOM对于大型XML文件不是一个好主意,但您当前的体系结构需要DOM,我担心您需要将DOM抽象出来,并用一个能够提取(并可能修改)您感兴趣的内容的API替换它。在一个大的组织中,你可以把这个话题带到架构师那里,并以一个必须具备的优先级将他们作为一个主要的重新设计来展示

如果您更幸运地得到架构师和管理层的承诺,那么您从未去过的国家的一些外包编程人员将得到下一个大的积压项目;-)

为了告诉您数据格式对性能的影响程度,我创建了一个包含一百万个整数的文件。我确实使用了3种不同的数据格式

  • 二进制40MB
  • ASCII文本文件80 MB(ddd\r\nddd\r\n…)
  • Xml文件170 MB(1\r\n2….)
然后我在64位进程中读取了它们

  • 通过内存映射文件的0,1s二进制文件
  • 0,5s二进制读取器
  • 2,5s文本文件
  • 5,3s XmlReader(流媒体)
  • 8,6s XDocument.Load

除了XDocument.Load导致了1.2GB的内存峰值外,内存消耗在~200MB处基本持平。您的性能目标可能不同,但我会首先通过流式XmlReader将Xml内容转换为二进制格式,这样可以更快地加载。

您是否尝试过使用
XDocument
?我不知道这是否会有帮助,但另一种方法是使用
XmlReader
并在节点读入时对其进行操作。搜索“SAX解析器C#”,您会找到一些方法,其中许多方法可能会像Oded提到的那样在封面下使用XmlReader。@Jim:SAX是一个完全不同的模型,这需要重写当前使用DOM的整个代码库。(关键是要避免这种情况)好吧,即使你横穿整个DOM,你真正需要的只是一次将迭代指针保存在内存中的点。子/父/等。元素可以在请求时从磁盘“水合”,而不是一次分配。这听起来可能,但很难在速度和内存消耗之间达成合理的折衷。我仍然不认为您会改变访问数据的方式。DOM是一种全内存模型。如果数据不适合存储,则需要对所读内容进行更多选择。所使用的Api需要反映这一点,否则Api的用户仍然(错误地)认为他们可以反复查询文件,而性能影响很小,因为所有内容都已经在内存中了。+1流式处理是可行的。或者将其从Xml转换为二进制格式,无需任何解析即可快速读取。