C# .Net SaxonApi 抛出内存异常
C# .Net SaxonApi throwing out of memory exception
机器配置是 4CPU 16 GB RAM 并试图处理 800MB 和 300MB XML 文件。有时 .NET Saxon API 会在堆栈跟踪下方抛出内存不足异常。查看前几个小时的 perfstats,服务器似乎有 10GB 可用内存。下面的代码是 运行 在并行任务中使用 Task.Run() 请指教。
DocumentBuilder documentBuilder = processor.NewDocumentBuilder();
documentBuilder.IsLineNumbering = true;
documentBuilder.WhitespacePolicy = WhitespacePolicy.PreserveAll;
XdmNode _XdmNode = documentBuilder.Build(xmlDocumentToEvaluate);
System.Exception: Error in ExecuteRules method ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at net.sf.saxon.tree.tiny.TinyTree.condense(Statistics )
at net.sf.saxon.tree.tiny.TinyBuilder.close()
at net.sf.saxon.event.ProxyReceiver.close()
at net.sf.saxon.pull.PullPushCopier.copy()
at net.sf.saxon.event.Sender.sendPullSource(PullSource , Receiver , ParseOptions )
at net.sf.saxon.event.Sender.send(Source source, Receiver receiver, ParseOptions options)
at net.sf.saxon.Configuration.buildDocument(Source source, ParseOptions parseOptions)
at net.sf.saxon.Configuration.buildDocument(Source source)
at Saxon.Api.DocumentBuilder.Build(XmlReader reader)
at Saxon.Api.DocumentBuilder.Build(XmlNode source)
对于 800Mb 的输入文件,我认为您可能会开始达到实际可用堆内存量以外的限制,例如数组或字符串的最大大小。这可能就是您看到的效果。 TinyTree 节省 space 的一种方法是使用少量大对象而不是大量小对象,因此它可以触发此效果。
TinyTree.condense() 方法(这是它失败的地方)在树构造结束时被调用,并尝试回收用于 TinyTree 数据结构的数组中未使用的 space。这是通过分配较小的数组达到实际使用的大小,并复制数据来完成的。所以暂时它需要额外的内存,这就是发生故障的地方。查看代码,实际上有机会减少所需的临时内存量。
如果您的数据中有很多重复的文本或属性值,那么使用 "TinyTreeCondensed" 选项可能是值得的,该选项试图将这些值统一起来。但是如果没有这样的重复,这可能会适得其反,因为 space 在树构建过程中用于索引。
对于这么大的数据,我认为检查替代策略是个好主意。例如:XML 个数据库;流式处理;将文件拆分为多个文件;文档投影。如果不了解您要解决的问题的全局,就不可能就此提出建议。
机器配置是 4CPU 16 GB RAM 并试图处理 800MB 和 300MB XML 文件。有时 .NET Saxon API 会在堆栈跟踪下方抛出内存不足异常。查看前几个小时的 perfstats,服务器似乎有 10GB 可用内存。下面的代码是 运行 在并行任务中使用 Task.Run() 请指教。
DocumentBuilder documentBuilder = processor.NewDocumentBuilder();
documentBuilder.IsLineNumbering = true;
documentBuilder.WhitespacePolicy = WhitespacePolicy.PreserveAll;
XdmNode _XdmNode = documentBuilder.Build(xmlDocumentToEvaluate);
System.Exception: Error in ExecuteRules method ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at net.sf.saxon.tree.tiny.TinyTree.condense(Statistics )
at net.sf.saxon.tree.tiny.TinyBuilder.close()
at net.sf.saxon.event.ProxyReceiver.close()
at net.sf.saxon.pull.PullPushCopier.copy()
at net.sf.saxon.event.Sender.sendPullSource(PullSource , Receiver , ParseOptions )
at net.sf.saxon.event.Sender.send(Source source, Receiver receiver, ParseOptions options)
at net.sf.saxon.Configuration.buildDocument(Source source, ParseOptions parseOptions)
at net.sf.saxon.Configuration.buildDocument(Source source)
at Saxon.Api.DocumentBuilder.Build(XmlReader reader)
at Saxon.Api.DocumentBuilder.Build(XmlNode source)
对于 800Mb 的输入文件,我认为您可能会开始达到实际可用堆内存量以外的限制,例如数组或字符串的最大大小。这可能就是您看到的效果。 TinyTree 节省 space 的一种方法是使用少量大对象而不是大量小对象,因此它可以触发此效果。
TinyTree.condense() 方法(这是它失败的地方)在树构造结束时被调用,并尝试回收用于 TinyTree 数据结构的数组中未使用的 space。这是通过分配较小的数组达到实际使用的大小,并复制数据来完成的。所以暂时它需要额外的内存,这就是发生故障的地方。查看代码,实际上有机会减少所需的临时内存量。
如果您的数据中有很多重复的文本或属性值,那么使用 "TinyTreeCondensed" 选项可能是值得的,该选项试图将这些值统一起来。但是如果没有这样的重复,这可能会适得其反,因为 space 在树构建过程中用于索引。
对于这么大的数据,我认为检查替代策略是个好主意。例如:XML 个数据库;流式处理;将文件拆分为多个文件;文档投影。如果不了解您要解决的问题的全局,就不可能就此提出建议。