How to Speed Up Apache Xalan’s XPath Processor by Factor 10x

About Lukas Eder

There has been a bit of an awkward bug in Apache Xalan for a while now, and that bug is XALANJ-2540. The effect of this bug is that an internal SPI configuration file is loaded by Xalan thousands of times per XPath expression evaluation, which can be measured easily as such:
 
 
 
 
 
 
 
this:

Element e = (Element)  document.getElementsByTagName("SomeElementName")          .item(0);String result = ((Element) e).getTextContent();

Seems to be an incredible 100x faster than this:

// Accounts for 30%, can be cachedXPathFactory factory = XPathFactory.newInstance();// NegligibleXPath xpath = factory.newXPath();// NegligibleXPathExpression expression =  xpath.compile("//SomeElementName");// Accounts for 70%String result = (String) expression  .evaluate(document, XPathConstants.STRING);

It can be seen that every one of the 10k test XPath evaluations led to the classloader trying to lookup the DTMManager instance in some sort of default configuration. This configuration is not loaded into memory but accessed every time. Furthermore, this access seems to be protected by a lock on the ObjectFactory.class itself. When the access fails (by default), then the configuration is loaded from the xalan.jar file’s configuration file:

META-INF/service/org.apache.xml.dtm.DTMManager

Every time!:

A profiling session on Xalan

A profiling session on Xalan

Fortunately, this behaviour can be overridden by specifying a JVM parameter like this:

-Dorg.apache.xml.dtm.DTMManager=  org.apache.xml.dtm.ref.DTMManagerDefault

or

-Dcom.sun.org.apache.xml.internal.dtm.DTMManager=  com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault

The above works, as this will allow to bypass the expensive work in lookUpFactoryClassName() if the factory class name is the default anyway:

// Code from c.s.o.a.xml.internal.dtm.ObjectFactorystatic String lookUpFactoryClassName(       String factoryId,       String propertiesFilename,       String fallbackClassName) {  SecuritySupport ss = SecuritySupport    .getInstance();  try {    String systemProp = ss      .getSystemProperty(factoryId);    if (systemProp != null) {       // Return early from the method      return systemProp;    }  } catch (SecurityException se) {  }  // [...] "Heavy" operations later

Resources

The above text is an extract from a Stack Overflow question and answer that I’ve contributed to the public a while ago. I’m posting it again, here on my blog, such that the community’s awareness for this rather heavy bug can be raised. Feel free to upvote on this ticket here, as every Sun/Oracle JDK on this planet is affected: https://issues.apache.org/jira/browse/XALANJ-2540

Contributing a fix to Apache would be even better, of course…
 

Related Whitepaper:

Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code

Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!

To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.

Get it Now!  

Leave a Reply


eight − = 6




Source : http://www.javacodegeeks.com/2013/09/how-to-speed-up-apache-xalans-xpath-processor-by-factor-10x.html

Back to Top