IBM Support

XSLT transformations cause high CPU and slow performance

Troubleshooting


Problem

Applications that do many XSLT Transformations show spikes in CPU.

Symptom

High CPU and slower performance may be noticed in applications that have been migrated from WAS 6.1 and earlier to WAS 7.0 or later.

Cause

The XL TXE-J compiler compiles more slowly and uses more CPU and memory than the predecessor XSLT4J interpreter. This is because it does optimizations to improve runtime performance. However, if the application compiles the stylesheet every time it is used, or only uses the stylesheet to do a few transformations then the extra compile time will outweigh the improved runtime performance and the transformation will run more slowly overall.

Diagnosing The Problem

Use data collected during the high CPU from the appropriate Performance MustGather:


Determine which threads are consuming the most CPU:

The issue is highly likely to XSLT processing if the suspect threads have many thread stacks which contain the following:
      ...TransformerFactory.new...
      AND
      ...XSLTCompiler.compile...

Resolving The Problem

See: IBM User Guides for Java V6 on 64-bit AIX > User Guide > Developing Java applications > Using XML - Migrating to the XL-TXE-J (See point 6)

"For best performance, ensure that you are not recompiling XSLT transformations that can be reused.

Use one of the following methods to reuse compiled transformations:

    If your stylesheet does not change at run time, compile the stylesheet as part of your build process and put the compiled classes on your classpath. Use the org.apache.xalan.xsltc.cmdline.Compile command to compile the stylesheet and set the "http://www.ibm.com/xmlns/prod/xltxe-j/use-classpath" transformer factory attribute to true to load the classes from the classpath.

    If your application will use the same stylesheet during multiple runs, set the "http://www.ibm.com/xmlns/prod/xltxe-j/auto-translet" transformer factory attribute to true to automatically save the compiled stylesheet to disk for reuse. The compiler will use a compiled stylesheet if it is available, and compile the stylesheet if it is not available or is out-of-date. Use the "http://www.ibm.com/xmlns/prod/xltxe-j/destination-directory" transformer factory attribute to set the directory used to store compiled stylesheets. By default, compiled stylesheets are stored in the same directory as the stylesheet.

    If your application is a long-running application that reuses the same stylesheet, use the transformer factory to compile the stylesheet and create a Templates object. You can use the Templates object to create Transformer objects without recompiling the stylesheet. The Transformer objects can also be reused but are not thread-safe.

    If your application uses each stylesheet just once or a very small number of times, or you are unable to make any of the other changes listed in this step, you might want to continue to use the XSLT4J interpreter by setting the javax.xml.transform.TransformerFactory service provider to "org.apache.xalan.processor.TransformerFactoryImpl."


To use the (non-default) interpreter, there are two ways to switch to the interpreter:
    1) TransformerFactory tFactory =TransformerFactory.newInstance("org.apache.xalan.processor.TransformerFactoryImpl", null);

    OR

    2) Set the following system property. (Note: this would affect all transformations in the JVM):

    -Djavax.xml.transform.TransformerFactory=org.apache.xalan.processor.TransformerFactoryImpl
    Note:
    The interpreter compiles quickly but does not execute that quickly. It is good when a Transformer or Templates object will only be used a few times.

    The (default) compiler on the other hand, compiles slowly and is memory and cpu intensive but executes much faster. It is good when a Transfomer or Templates object will be used many times (to transform many input sources).

To use the (default) compiler to compile once and reuse the same stylesheet over and over to process many input documents, cache the compiled templates object:

private synchronized Templates getTemplates(String xslPath) throws Exception {
Templates templates = templatesCache.get(xslPath);
if (templates == null) {
TransformerFactory factory = TransformerFactory.newInstance();
templates = factory.newTemplates(new StreamSource(xslPath));
templatesCache.put(xslPath, templates);
}
return templates;
}

public void runTransformation(String xslPath, String xmlPath) throws Exception {
Templates templates = getTemplates(xslPath);
Transformer transformer = templates.newTransformer();
transformer.transform(new StreamSource(xmlPath), new StreamResult(System.out));
}

[{"Product":{"code":"SSEQTP","label":"WebSphere Application Server"},"Business Unit":{"code":"BU053","label":"Cloud & Data Platform"},"Component":"--","Platform":[{"code":"PF002","label":"AIX"},{"code":"PF016","label":"Linux"},{"code":"PF033","label":"Windows"}],"Version":"8.5;8.0;7.0","Edition":"","Line of Business":{"code":"LOB45","label":"Automation"}}]

Document Information

Modified date:
15 June 2018

UID

swg21641274