【问题标题】:Using discard-document with saxon and xquery将丢弃文档与 saxon 和 xquery 一起使用
【发布时间】:2015-12-29 16:15:41
【问题描述】:

我正在尝试查找有关如何使用 Saxon 的丢弃文档功能的示例。我有大约 50 个文件,每个文件 40mb,所以它们在我的 xquery 脚本中使用了大约 4.5GB 的内存。

我尝试在每次调用 XML 文件后使用saxon:discard-document(doc("filename.xml")),但这可能不是正确的方法吗?使用后内存使用没有区别。

我还发现了一些关于它使用的问题(7 年前),他们建议使用丢弃文档运行 xpath。但是我对该文档有很多调用,因此我必须将所有声明替换为saxon:discard-document(doc("filename.xml"))/xpath/etc/etc/etc

谢谢

【问题讨论】:

标签: xquery saxon


【解决方案1】:

我认为这是一个很好的问题,没有太多可用的信息,所以我会尝试自己回答。

这是一个关于如何使用 saxon:discard-document 的示例:

declare function local:doStuffInDocument($doc as document-node()) {
  $doc//testPath
};

let $urls := ("http://url1", "http://url2")
let $results :=
for $url in $urls
  let $doc := saxon:discard-document(doc($url))
  return local:doStuffInDocument($doc)      
return $results    

通过使用类似的代码,我设法将内存消耗从 4+GB 减少到仅 300MB。

要了解 discard-document 的作用,请查看 Michael Kay 在 SF maillist 上的精彩评论:

只是解释一下 discard-document() 的作用:

Saxon 维护(由 Transformer/Controller 拥有)一个表 将文档 URI 映射到文档节点。当你调用 document() 函数,Saxon 会查看 URI 是否在此表中,以及是否 即,它返回相应的文档节点。如果不是,则读取 并解析在该 URI 中找到的资源。的效果 saxon:discard-document() 是从 这个映射表。 (当然,如果一个文档引用自此 table 那么垃圾收集器会将文档保存在内存中;如果 它没有从表中引用,那么它就有资格 垃圾收集。如果它被引用,它不会被垃圾收集 来自一个全局变量;但它仍然不会出现在表格中 另一个对 document() 的调用再次使用相同 URI 的事件。)

另一个来自 Michael Kay 在 Altova maillist

在撒克逊语中,如果你使用 doc() 或 document() 函数,那么文件 将被加载到内存中,并一直在内存中直到结束 运行,以防它再次被引用。所以你会打同样的 许多小文件和一个大文件一样的内存问题 - 事实上,更糟糕的是,因为每个文档的开销很大。

但是,有一个解决方法:扩展函数 saxon:discard-document() 导致文档被丢弃 垃圾收集器一旦没有更多的内存 引用它。

【讨论】:

    【解决方案2】:

    了解幕后实际发生的事情可能很有用。 doc() 函数在缓存中查找文档是否已经存在;如果没有,它会读取文档,将其添加到缓存中,然后返回。 discard-document() 函数查看文档是否在缓存中,如果存在则将其删除,然后将其返回。通过从缓存中删除文档,当文档不再被引用时,它可以进行垃圾回收。如果使用 discard-document 对内存消耗没有影响,那可能是因为还有其他东西仍在引用该文档 - 例如,全局变量。

    【讨论】:

    • 嗨,迈克尔,感谢您的宝贵时间。我已经从 SourceForge 邮件列表中找到(并保存以供将来参考)您的评论。我已将此添加到我的答案中,以防它对更多人有所帮助。
    猜你喜欢
    • 2016-08-21
    • 2012-06-28
    • 1970-01-01
    • 2014-03-30
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    相关资源
    最近更新 更多