United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-5047031 : Tiger's XSLTC uses DocumentBuilderFactory lookup for each NodeList result

Details
Type:
Bug
Submit Date:
2004-05-13
Status:
Resolved
Updated Date:
2012-04-25
Project Name:
JDK
Resolved Date:
2004-06-06
Component:
xml
OS:
windows_xp
Sub-Component:
javax.xml.transform
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.2.3
Fixed Versions:
1.3.0 (1.3)

Related Reports
Backport:
Backport:

Sub Tasks

Description
Name: gm110360			Date: 05/13/2004


FULL PRODUCT VERSION :
1.5.0-beta-b32c

ADDITIONAL OS VERSION INFORMATION :
Windows XP (5.1, Build 2600.xpsp2.030...)

A DESCRIPTION OF THE PROBLEM :
[Note: I posted this against JAXP 1.2.3 as there is no selection for Tiger]

I'm using Tiger's XSLTC with extension functions. One of my functions returns a org.w3c.dom.NodeList which XSLTC translates into a an internal DOM iterator (see com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary#nodeList2Iterator).

This method is called after each invocation of the extension function.  Each time it will locate a Dom implementation through the JAXP factory interface. This is a very expensive operation as it searches through the whole classpath. It actually dominates processing time, as I can see when doing threaddumps.

After replacing that code to create a new org.apache.xerces.dom.DocumentImpl, I got a factor of 5 higher transformation throughput. In a setting with more complicated classloaders as in a J2EE container, the impact is likely to be even higher.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
  From a stylesheet, call an extension function that returns a NodeList:
<xsl:template match="*">
  <xsl:copy-of select="java:my.Class.function()" />
</xsl:template>

with

Class {
  static final NodeList result = DocumentBuilder.newInstance().newDocument().createDocumentFragment().getChildNodes();
  public static NodeList function() {
    return result;
  }
}

Call this transformation in a loop. Do threaddumps.



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Speedy transformations. No anomalies in the stack traces.
ACTUAL -
Transformation was rather slow (1.6ms). After the proposed change it was down to 0.4ms

The following fragment was dominating the processing time:

"main" prio=5 tid=0x0003e210 nid=0x874 runnable [0x0007e000..0x0007fc3c]
	at java.io.BufferedReader.<init>(BufferedReader.java:91)
	at org.apache.xerces.util.ObjectFactory.findJarServiceProvider(Unknown Source)
	at org.apache.xerces.util.ObjectFactory.createObject(Unknown Source)
	at org.apache.xerces.util.ObjectFactory.createObject(Unknown Source)
	at org.apache.xerces.parsers.DOMParser.<init>(Unknown Source)
	at org.apache.xerces.parsers.DOMParser.<init>(Unknown Source)
	at org.apache.xerces.jaxp.DocumentBuilderImpl.<init>(Unknown Source)
	at org.apache.xerces.jaxp.DocumentBuilderFactoryImpl.newDocumentBuilder(Unknown Source)
	at com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary.nodeList2Iterator(BasisLibrary.java:1172)
	at GregorSamsa.template$dot$0()




REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * Copyright (c) 2004 CoreMedia AG, Hamburg. All rights reserved.
 */
package test;

import org.w3c.dom.NodeList;

import javax.xml.transform.Templates;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;


public class XsltPerformance {
  public static void main(String[] args) throws TransformerException {
    String xml = "<root/>";
    String xsl =
	    "<xsl:transform version=\"1.0\"\n" +
	    "  xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" +
	    "  xmlns:java=\"http://xml.apache.org/xalan/java\"\n" +
	    "  exclude-result-prefixes=\"java\"\n" +
	    "  >" +
	    " <xsl:template match=\"/\">" +
	    "   <xsl:copy-of select=\"java:test.XsltPerformance.empty()\"/> "+
	    " </xsl:template>"+
	    "</xsl:transform>";

    Templates templates = new com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl().newTemplates(new StreamSource(new StringReader(xsl)));

    while(true) {
      StreamResult devNull = new StreamResult(new ByteArrayOutputStream());

      long start = System.currentTimeMillis();
      for(int i=0; i<1000; i++) {
        templates.newTransformer().transform(new StreamSource(new StringReader(xml)), devNull);
      }
      System.out.println(System.currentTimeMillis()-start);
    }
  }

  static final NodeList EMPTY = new com.sun.org.apache.xerces.internal.dom.DocumentImpl().createDocumentFragment().getChildNodes();
  public static NodeList empty() {
    return EMPTY;
  }
}

---------- END SOURCE ----------
(Incident Review ID: 265357) 
======================================================================

                                    

Comments
EVALUATION

A DOMImplementation is now cached for even better performance. Translet now stores a reference to the DocumentBuilderFactory which is used by NodeList2Iterator() in the BasisLibrary.
Bug has been fixed in Apache and main-trunk of xalan internal workspace.

###@###.### 2004-05-27
                                     
2004-05-27
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.3
tiger-rc

FIXED IN:
1.3
tiger-rc

INTEGRATED IN:
1.3
tiger-b55
tiger-rc


                                     
2004-07-08



Hardware and Software, Engineered to Work Together