gpt4 book ai didi

java | XML 按大小分割 | HashMap 性能问题 | OOM 堆空间错误

转载 作者:行者123 更新时间:2023-12-01 20:05:31 26 4
gpt4 key购买 nike

需求是将大于5MB的XML文档分割成更小的文档 block ,以支持目标系统接受和处理它/它们。因为 XSLT v2 似乎不支持按大小分割 XML 文档,所以我们最终编写了一个 java 程序。当文档较小或小于 10 MB 时,该程序运行良好。当输入 32 MB 的文件时,程序就会失败。该程序作为代理工作,并插入到最大内存设置为 25GB 的 JVM。尽管如此,我们仍然会看到 OOM 堆空间错误。生成堆转储文件显示以下问题嫌疑人 1:

sun.misc.Launcher$AppClassLoader @ 0x1bb7ae098" occupies 156,512,240 (64.62%) bytes. The memory is accumulated in one instance of 

基于此,我开始检查程序并推断出一个可能引发内存问题的点,即[您可能会忽略一些系统输出,因为它们是为我的调试 session 添加的]:

public static HashMap < Integer, String > splitPromotionItem(List promotionsItems, int promotionItemMaxSizeUoMNumericValue, int promotionItemMaxSize, String routingLocation, String docNum, XDNode messageHeader, XDNode promotionsData){
HashMap < Integer, String > promotionItemMap = new HashMap < Integer, String > ();
int totalSubMessage = 1;
String promotionsItemsData = "";
int promotionsItemsSize = 0;
String promotionsItemsDataTemp = "";
int i = 0;
int q = 1;
do {
promotionsItemsSize = promotionsItemsSize + ((XDNode) promotionsItems.get(i)).flatten().getBytes().length;
promotionsItemsData = promotionsItemsData + ((XDNode) promotionsItems.get(i)).flatten();

if (promotionsItemsSize > (promotionItemMaxSize * 1024 * 1024)) {
System.out.println("Inside First If: " + promotionsItems.size() + ": " + q++);
promotionsItemsSize = promotionsItemsSize - ((XDNode) promotionsItems.get(i)).flatten().getBytes().length;
promotionsItemsData = promotionsItemsDataTemp;
promotionItemMap.put(totalSubMessage++, promotionsItemsData);
if (i != (promotionsItems.size() - 1)) {
System.out.println("Inside Second If: " + promotionsItems.size());
i--;
promotionsItemsSize = 0;
promotionsItemsData = "";
} else {
System.out.println("Inside Second Else: " + promotionsItems.size());
promotionsItemsSize = ((XDNode) promotionsItems.get(i)).flatten().getBytes().length;
promotionsItemsData = ((XDNode) promotionsItems.get(i)).flatten();
}
}
if (promotionsItemsSize < (promotionItemMaxSize * 1024 * 1024) && (i) == (promotionsItems.size() - 1)) {
promotionItemMap.put(totalSubMessage++, promotionsItemsData);
}
i++;
promotionsItemsDataTemp = promotionsItemsData;
} while (i < promotionsItems.size());

return promotionItemMap;
}

该程序似乎首先将大型 XML 文档分割成较小的 block ,这些 block 存储在 HashMap 中,然后将其提供给一个函数,该函数迭代映射中的每个条目并写入文件。文件的名称和其中的元素之一带有文件在拆分批处理中的索引以及总拆分计数,以便于识别。

我最初的想法是将代码修改为:不将较小的 XML block 收集到 HashMap 中,而是直接将它们写入文件。这还要求在将所有较小的 block 保存到磁盘后,我必须重新打开它们以更新其内容以反射(reflect)文件索引和总计数以及文件本身的名称。

有没有更好的方法来处理这个问题?请帮忙。

注意:JVM 每天处理大量数据,并具有以下启动选项,我们使用 saxon 作为 xslt 处理器:

-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl -Xmx15360M -Xrs -XX:GCTimeRatio=5 -XX:+PrintGCDetails -Xloggc:<location> -XX:MinHeapFreeRatio=25 -XX:MaxHeapFreeRatio=60

更新29112017

XDNode 类及其扁平化函数的使用是使用 iWay 提供的 API 扩展程序的结果,以便能够将代理插入到其 JVM 中以无缝执行流程。这是XDNode的官方定义:

XDNode 是 XML 树的单个元素。完整的文档是 XDNode 的树。 XDNode 类和树专为快速解析和搜索以及在应用程序中轻松操作而设计。可以使用方法在 XDNode 树和标准 JDOM 树之间进行转换。所有服务器操作都在 XDNode 树上执行。

函数flatten()将整个XML文档作为字符串返回。

以下是 XML 文档的示例:

Sample XML Document

拆分操作在元素/SalonApps/Promotion/PromotionData/PromotionItem 处执行。我们迭代 PromotionItem 的每次出现,并将迭代的 block 存储在临时变量中,如上面的代码所示。我们还在每次迭代开始时检查大小是否超过限制 5 MB [在类的开头定义],以确定是否需要执行打包和文件写入操作。当大小较小时,迭代进一步进行以收集和存储。文档的 header 部分 [/SalonApps/Promotion/MessageHeader] 将添加到每个拆分文档中,并修改 MessageID 的值以反射(reflect)批处理中拆分消息的索引以及位置 2 和 3 处的批处理总数。值由连字符分隔。

我们仅支持 XSLT v1 和 v2。如果 XSLT v1 或 v2 可用于按 XML 文档的大小拆分文档,那就太好了。

最佳答案

我发现很难准确理解您想要做什么,通过对示例代码进行逆向工程来获得任何见解当然非常困难。但您已经表达了对 XSLT 解决方案的兴趣,因此这里有一个建议。

如果您的文档本质上是以下形式的平面结构:

<table>
<record>...</record>
<record>...</record>
...
</table>

如果记录数是文档大小的合理代理,那么您可以使用以下方法轻松地将其拆分为片段,每个片段的最大大小为 N(记录)

<xsl:template match="table">
<xsl:for-each-group select="record" group-adjacent="(position()-1) idiv $N">
<xsl:result-document href="part{position()}">
<table>
<xsl:copy-of select="current-group()"/>
</table>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>

另请注意,如果您使用 XSLT 3.0,则此解决方案是可流式传输的(尽管在开始处理 200Mb 或更多数据之前,不需要流式传输)。

如果这不是您想要做的,那么您需要更清楚地解释您的要求。

关于 java | XML 按大小分割 | HashMap 性能问题 | OOM 堆空间错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47474329/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com