我每次必须定期在 1 个文件夹中转换大量 XML 文件(最少 100K)(基本上,从解压缩的输入数据集中),我想学习如何以最有效的方式做到这一点。我的技术堆栈由 XLT 和 Saxon XSLT Java 库组成,它们是从 Bash 脚本调用的。它运行在具有 8 个内核的 Ubuntu 服务器和具有 64Gb 内存的 SSD RAID 上。请记住,我很好地处理了 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% 状态)。
简而言之,这是我迄今为止的所有建议/方法:
- 在子文件夹之间拆分整个 XML 文件(例如,包含每个 5K 文件),并将其用作在每个子文件夹的并行转换脚本中运行的一种方式
- 专门使用Saxon- EE库 (允许多线程执行)和
collection()
函数来解析 XML 文件 - 设置任务数量较少的 Java 环境,或减少每个进程的内存
- 指定 Saxon 是否与 XSLT 表兼容
libxml/libxslt
(不是仅适用于 XSLT1.0 吗?) - 使用专门的外壳,例如
xmlsh
我可以处理解决方案#2,它应该直接启用控制循环并仅加载一次JVM;#1 似乎更笨拙,我仍然需要在 Bash 中改进(负载分布和性能,处理相对/绝对路径);#3、#4 和 #5 对我来说是全新的,我可能需要更多解释来了解如何解决这个问题。
任何投入将不胜感激。