将样式表应用于xml文档的内存最少的方法是什么?

时间:2012-09-26 16:34:51

标签: java xml xslt memory websphere-7

考虑到我有一个XML文档作为byte []加载,大小为5MB。作为一个字节数组,它占用了5MB的内存。我有一个样式表Source,我想将其应用于此文档并执行如下所示的操作。

final TransformerFactory transformerFactory = TransformerFactory.newInstance();
final Transformer transformer = transformerFactory.newTransformer(styleSheet);

transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

final StringWriter writer = new StringWriter();

transformer.transform(convertStringToSource(filePayload), new StreamResult(writer));

return writer.getBuffer().toString().getBytes();

在服务器上运行时(WebSphere App Server 7 - 对连续的内存分配有限制)我得到堆转储,表明创建了10-15 MB的对象。我假设transform()方法将在内部创建一个对象,将原始xml存储为对象,将样式表存储为对象,将结果存储为对象。将它们加在一起,我至少要2*input+stylesheet MB。有没有更有效的方法来做到这一点,这可以将我的足迹降到最低?

你可能会说 - 它只有10MB,但就我而言,性能至关重要。当我必须一次转换数百或数千个文档时,分配那么多连续内存所花费的时间就会增加。因此,我们的服务器管理员将此限制设置为一种警告,分配的内存比建议的内存多。

仅供参考,以下JVM参数在WebSphere中设置它:-Xdump:stack:events=allocation,filter=#5m​

2 个答案:

答案 0 :(得分:1)

(我相信M. Kay会在此期间加入)

AFAIK XSL转换总是在内存中完成;我不知道任何流式XSL转换器实现(我想这很难,因为整个XML树在XSLT中总是'可见')。

我们发现撒克逊人的整体表现要比Xalan好得多。花费更少的时间处理文档是通过在相同的时间段内处理具有相同内存量的更多文档来提高性能的另一种方式。

Saxon有(自己?)自己的DocumentBuilder实现,但我们没有注意到使用它代替Xerces的内存增益。

对于大型XML文档,我们使用(流)map / reduce算法将它们拆分成较小的片段,然后再通过XSL运行它们。我们的map / reduce代码位于XML Dog的顶部

答案 1 :(得分:1)

原始XML大小与内存中树的大小之间的3倍扩展当然是正常的;实际上它很低。请参阅示例http://dev.saxonica.com/blog/mike/2012/09/

对于有限的一类转换,流式转换开始成为可能。请参阅示例http://www.saxonica.com/documentation/sourcedocs/streaming.xml。但是当你的文件只有5Mb时,我不确定这是否适合你,至少在没有进一步证据的情况下是这样。

在我看来,您已经得出结论,XSLT处理器的内存分配是影响工作负载性能的关键因素,而没有任何真实证据证明是这种情况。例如,看到转换时间与解析时间相关的内容将会很有趣 - 很多人都感到惊讶的是,与解析成本相比,转换成本有时很小。在解决系统性能的一个方面之前,您需要弄清楚真正的瓶颈是什么。