我有一个应用程序,它定期读取大量的XML文件(大约20-30个),比如每10分钟读取一次。现在,每个XML文件的大小可以近似为至少40-100MB。一旦读取了每个XML,就从文件中创建一个映射,然后该映射跨处理器链(10-15)传递,每个处理器使用数据,执行一些过滤或写入数据库等。
现在,该应用程序正在32位JVM中运行。现在还没有迁移到64位JVM的打算。正如预期的那样,内存占用非常高...接近32位JVM的阈值。现在,当我们收到大文件时,我们将生成的map序列化到磁盘中,并并发运行最多3-4个map的处理器链,就像我们试图同时处理所有map一样,它很容易就会OutOfMemory。此外,垃圾收集也相当高。
我有一些想法,但想看看是否有一些选择,人们已经尝试/评估。那么,扩展这类应用程序有哪些选择呢?
发布于 2011-09-10 14:28:05
是的,为了模仿@aaray和@MeBigFatGuy,你需要使用一些基于事件的解析器,比如前面提到的dom4j,或者SAX或StAX。
举个简单的例子,如果批量加载100MB的XML,那么它至少会消耗200MB的RAM,因为每个字符都会立即扩展为一个16位字符。
接下来,任何不使用的元素标记都将消耗额外的内存(加上节点的所有其他负担和记账),这一切都是浪费的。如果您正在处理数字,如果数字大于2位,则将原始字符串转换为长字符串将是一个净胜利。
您是否考虑过能够通过外部XSLT运行XML,以消除在XML进入JVM之前不想处理的所有问题?有几个独立的命令行XSL处理程序,您可以使用它们将文件预处理为更合理的处理方式。这真的取决于你实际使用了多少进来的数据。
通过使用基于事件的XML处理模型,XSLT步骤非常多余。但是基于事件的模型基本上都不好用,所以使用XSLT步骤可能会让您重用一些现有的DOM逻辑(假设您正在做的就是这样)。
你的内部结构越扁平,它们在内存方面就越便宜。实际上,运行32bVM有一点优势,因为实例指针的大小是它的一半。但是,当您谈论1000个或数百万个节点时,所有这些都会很快地积累起来。
发布于 2011-09-10 13:16:08
我们在处理大型XML文件(大约400Mb)时也遇到了类似的问题。我们使用以下代码极大地减少了应用程序的内存占用:
发布于 2011-09-11 21:44:50
您可以将每个XML文件的内容插入到一个临时DB表中,每个链接会获取所需的数据。您可能会损失性能,但获得可伸缩性。
https://stackoverflow.com/questions/7369135
复制相似问题