我每次都必须定期转换 1 个文件夹内的大量 XML 文件(至少 100K)(基本上,来自解压缩的输入数据集),并且我想了解如何以尽可能最有效的方式做到这一点。我的技术堆栈由 XLT 和 Saxon XSLT Java 库组成,从 Bash 脚本调用。它运行在具有 8 核和具有 64Gb RAM 的 SSD Raid 的 Ubuntu 服务器上。请记住,我可以很好地处理 XSLT,但我仍在学习 Bash 以及如何为此类任务正确分配负载(Java 在那时也几乎只是一个词)。
我之前创建了一篇关于此问题的帖子,因为我的方法似乎效率很低,实际上需要帮助才能正确运行(请参阅此SOF帖子)。后来有很多评论,以不同的方式呈现这个问题是有意义的,因此这篇文章。有人向我提出了几种解决方案,其中一种目前比我的要好得多,但它仍然可以更优雅和更高效。
现在,我正在运行这个:
printf -- '-s:%s\0' input/*.xml | xargs -P 600 -n 1 -0 java -jar saxon9he.jar -xsl:some-xslt-sheet.xsl
根据之前的一些测试,我设置了600个进程。更高只会引发 Java 内存错误。但它现在只使用 30 到 40Gb 的 RAM(尽管所有 8 个核心都处于 100%)。
简而言之,这里是到目前为止我所拥有的所有建议/方法:
collection()
函数来解析 XML 文件libxml/libxslt
(不是只适用于XSLT1.0吗?)xmlsh
我可以处理解决方案#2,它应该直接启用控制循环并仅加载 JVM 一次; #1 似乎更笨拙,我仍然需要在 Bash 中进行改进(负载分配和性能,处理相对/绝对路径); #3、#4 和 #5 对我来说是全新的,我可能需要更多解释来了解如何解决这个问题。
如有任何意见,我们将不胜感激。
“尽可能最有效的方法”要求很高,而且通常不是一个合理的目标。例如,我怀疑您是否愿意投入 6 个月的努力来将流程效率提高 3%。您正在寻找一种能够满足性能目标并且可以以最小的努力实现的方法。而“效率”本身就引发了关于你的指标是什么的问题。
我非常有信心,我建议的设计,使用 collection() 和 xsl:result-document(两者在 Saxon-EE 中并行化)进行一次转换处理所有文件,能够给出良好的结果,并且可能比我考虑的唯一其他方法(即编写一个 Java 应用程序来保存“控制逻辑”)工作量要少得多:尽管如果您擅长编写多线程 Java 应用程序,那么您可能会得到它利用您对工作负载的了解来加快速度。
请尝试使用“GNU并行”而不是xargs在多台机器上分配任务。我没有使用过它,所以我预计会被否决。
我经常使用 Saxon 来运行 100 个文件。
你可以看看我的剧本。我从 XML 到 JSON 的转换比将 JSON 转换为 DOM 然后再转换为其他内容要慢得多。我不认为我的解决方案比你的更好。
ls -d“$@”| grep -v 中间 | grep -v“.new”|特氏 ' ' | xargs -0 -P "$PROCESSORS" java net.coderextreme.RunSaxon --- "${OVERWRITE}" --"${STYLESHEETDIR}/X3dToJson.xslt" -json | sed 's/^(.*)$/" "/' | xargs -P“$PROCESSORS”“${NODE}”“${NODEDIR}/json2all.js”
我会特别考虑使用 xargs 的 -L # 参数,这样你就可以将文件批处理为一次转换,但我不喜欢它。 YMMV。我只有 100 个左右的文件。
这是我调用 Saxon 的 Java 代码:
请谨慎使用!
https://github.com/coderextreme/X3DJSONLD/blob/master/src/main/java/net/coderextreme/RunSaxon.java