You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bu...@apache.org on 2017/12/08 16:07:13 UTC

[Bug 61875] New: Investigate whether Xalan can be removed

https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

            Bug ID: 61875
           Summary: Investigate whether Xalan can be removed
           Product: Taglibs
           Version: 1.2.5
          Hardware: PC
                OS: Mac OS X 10.1
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Standard Taglib
          Assignee: dev@tomcat.apache.org
          Reporter: nbmlaw@gmail.com
  Target Milestone: ---

Created attachment 35593
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=35593&action=edit
patch switching back to JAXP

I am currently evaluating whether the Xalan dependency can be dropped from
taglibs and replaced with javax.xml.*. 

this is the code that is blowing up for me:
Reader xsl = new InputStreamReader(filepath.openStream());
TransformerFactory transformerfactory = TransformerFactory.newInstance();
StreamSource ssXsl = new StreamSource(xsl);
ssXsl.setSystemId(filepath.toExternalForm());
Templates templates = transformerfactory.newTemplates(ssXsl);
Transformer transformer = templates.newTransformer();

last line causes:
java.lang.ClassCastException: org.apache.xml.dtm.ref.DTMManagerDefault cannot
be cast to org.apache.xml.dtm.DTMManager
    at org.apache.xml.dtm.DTMManager.newInstance(DTMManager.java:137)
    at org.apache.xpath.XPathContext.<init>(XPathContext.java:102)
    at org.apache.xpath.XPathContext.<init>(XPathContext.java:349)
    at org.apache.xpath.XPathContext.<init>(XPathContext.java:337)
    at
org.apache.xalan.transformer.TransformerImpl.<init>(TransformerImpl.java:397)
    at
org.apache.xalan.templates.StylesheetRoot.newTransformer(StylesheetRoot.java:200)

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #7 from Matthew Broadhead <nb...@gmail.com> ---
i stepped through ForEachTagTest.java

line 140 if (tag.doStartTag() == IterationTag.EVAL_BODY_INCLUDE) {
seems to take a long time

line 142 result = dot.evaluate(tag.getCurrent());
takes virtually no time but the iterations seem to add up to a lot of time in
total

i don't really understand the ins and outs but it seems like every element has
been split up and stored separately instead of being stored as an xml
structure.  so the xml search tools don't work very well it is like loading a
separate document for each search.

is there any way to access the low level dtm stuff through the javax.xml.*?

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #4 from Matthew Broadhead <nb...@gmail.com> ---
JSTLXPathContext needs to be set in ForEachTagTest.setup() somehow?

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #3 from Matthew Broadhead <nb...@gmail.com> ---
i tried running that test and i got 
javax.servlet.jsp.JspTagException: javax.xml.xpath.XPathExpressionException:
javax.xml.transform.TransformerException: Unable to evaluate expression using
this context
        at
org.apache.taglibs.standard.xpath.jaxp.JAXPXPathExpression.evaluate(JAXPXPathExpression.java:67)
        at
org.apache.taglibs.standard.xpath.jaxp.JAXPXPathExpression.iterate(JAXPXPathExpression.java:56)
        at
org.apache.taglibs.standard.tag.common.xml.ForEachTag.prepare(ForEachTag.java:57)
        at
javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(LoopTagSupport.java:241)
        at
org.apache.taglibs.standard.tag.common.xml.ForEachTagTest.testIterationPerformance(ForEachTagTest.java:261)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
        at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
        at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
        at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
        at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
        at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
        at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
        at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
        at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
        at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:539)
        at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
        at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
        at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)
Caused by: javax.xml.xpath.XPathExpressionException:
javax.xml.transform.TransformerException: Unable to evaluate expression using
this context
        at
com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:204)
        at
org.apache.taglibs.standard.xpath.jaxp.JAXPXPathExpression.evaluate(JAXPXPathExpression.java:65)
        ... 28 more
Caused by: javax.xml.transform.TransformerException: Unable to evaluate
expression using this context
        at com.sun.org.apache.xpath.internal.XPath.execute(XPath.java:368)
        at
com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.eval(XPathExpressionImpl.java:133)
        at
com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.eval(XPathExpressionImpl.java:109)
        at
com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:191)
        ... 29 more
Caused by: java.lang.RuntimeException: Unable to evaluate expression using this
context
        at
com.sun.org.apache.xpath.internal.axes.NodeSequence.setRoot(NodeSequence.java:266)
        at
com.sun.org.apache.xpath.internal.axes.LocPathIterator.execute(LocPathIterator.java:214)
        at com.sun.org.apache.xpath.internal.XPath.execute(XPath.java:339)
        ... 32 more
can you share your ForEachTagTest?

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #10 from Matthew Broadhead <nb...@gmail.com> ---
https://blogs.sap.com/2009/12/04/performance-improvements-in-nw-java-applications-with-xml-processing/

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

Jeremy Boynes <jb...@apache.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Depends on|                            |27717

--- Comment #1 from Jeremy Boynes <jb...@apache.org> ---
Original thread on taglibs-user:
http://mail-archives.apache.org/mod_mbox/tomcat-taglibs-user/201711.mbox/%3C66442bd7-e0db-31ec-00d3-76dd2f660b48%40nbmlaw.co.uk%3E

This problem has been seen on TomEE which does not include the Xalan dependency
needed by the XML tags.

Previous attempts to replace Xalan with JAXP did not solve the performance
issue reported in #27717. There were also problems with XML types that were
returned. See that issue for details.


Referenced Bugs:

https://bz.apache.org/bugzilla/show_bug.cgi?id=27717
[Bug 27717] <x:forEach> very slow in JSTL 1.1
-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #6 from romain.manni-bucau <rm...@gmail.com> ---
A compromise can surely be to make xalan optional with a static check if it is
here to select the impl. Also copying the needed classes should be doable if it
doesnt import the whole xalan.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #9 from Matthew Broadhead <nb...@gmail.com> ---
https://stackoverflow.com/questions/6340802/java-xpath-apache-jaxp-implementation-performance

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #2 from Jeremy Boynes <jb...@apache.org> ---
I applied the patch and made the ForEachTag tests work and am seeing the same
performance problem we had before.

With the current implementation the testIterationPerformance test completes
200K iterations in 1250ms. 

With the patched version, this test did not complete within a reasonable time.
When I lower the iteration count from 200K to 20K it completed in 46000ms. This
looks like the same n^2 behaviour we saw before the fix for 27717.

This is the test I ran with the modifications to work with JAXP:

    @Ignore
    @Test
    public void testIterationPerformance() throws Exception {
        // create a large document
        test = newBenchmarkDocument(20000);

        XPathExpression dot =
XPathFactory.newInstance().newXPath().compile(".");
        expect(pageContext.findAttribute("doc")).andStubReturn(test);
        tag.setSelect("$doc/root/a");
        replay(pageContext);
        long time = -System.nanoTime();
        String result = null;
        if (tag.doStartTag() == IterationTag.EVAL_BODY_INCLUDE) {
            do {
                result = dot.evaluate(tag.getCurrent());
            } while (tag.doAfterBody() == IterationTag.EVAL_BODY_AGAIN);
            tag.doFinally();
        }
        time += System.nanoTime();
        System.err.println("time = " + time / 1000000 + "ms.");
        assertEquals("199999", result);
    }

time = 46673ms.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #8 from Jeremy Boynes <jb...@apache.org> ---
(In reply to Matthew Broadhead from comment #7)
> i stepped through ForEachTagTest.java
> 
> line 140 if (tag.doStartTag() == IterationTag.EVAL_BODY_INCLUDE) {
> seems to take a long time
> 
> line 142 result = dot.evaluate(tag.getCurrent());
> takes virtually no time but the iterations seem to add up to a lot of time
> in total
> 
> i don't really understand the ins and outs but it seems like every element
> has been split up and stored separately instead of being stored as an xml
> structure.  so the xml search tools don't work very well it is like loading
> a separate document for each search.
> 
> is there any way to access the low level dtm stuff through the javax.xml.*?

The xpath engine in Xalan was designed to allow repeated fast evaluation of
xpath expressions during XSLT processing. It does that by taking an upfront hit
to build a DTM model of the document being processed, a model that is then
reused each time an xpath expression needs to be evaluated.

The current implementation mirrors that in the context of JSTL. It constructs
the model once in ForEachTag#doStartTag then reuses it when evaluating the
xpath expressions inside the loop just like the XSLT engine does. It takes
advantage of a portion of the JSTL spec that allows other implementations of
XML context than a DOM.

When using JAXP it is limited by the standard API to using DOM objects as
context. That means every time an XPath expression is evaluated, the engine has
to recreate the DTM model before it can evaluate the expression. It does that
starting from the root had has to work over the N-1 preceding nodes, hence the
O(N^2) behaviour.

In theory, the JAXP XPath API allows different "object models" to be selected.
See
 
https://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/xpath/XPathFactory.html#newInstance(java.lang.String)
so there may be a way to use DTM with the default JAXP implementation (which in
Oracle's and OpenJDK is a shaded version of Xalan which would support DTM). The
downside of this would be if there were other JDKs that did not support DTM.

I think Glassfish ended up simply shading Xalan and bundling it with their
implementation. We could do that as well, perhaps adding a "bundle" jar that
includes all the tags along with a shaded version of Xalan that was intended to
used by containers rather than applications.

So perhaps multiple packagings:
- pure JAXP, smaller but with a known performance issue with XML processing
- Xalan bundled, larger but with no performance issue
- unbundled, so application users can choose what tags and dependencies they
include

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #5 from Jeremy Boynes <jb...@apache.org> ---
Created attachment 35598
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=35598&action=edit
JAXP with perf test

$ mvn -Dtest=ForEachTagTest#testIterationPerformance -DfailIfNoTests=false test
...

Running org.apache.taglibs.standard.tag.common.xml.ForEachTagTest
time = 39511ms.
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 39.729 sec

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


[Bug 61875] Investigate whether Xalan can be removed

Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=61875

--- Comment #11 from Matthew Broadhead <nb...@gmail.com> ---
i have just tried TomEE 8.0.0-SNAPSHOT and it is working better than 7.0.4.  i
can transform xml on loadup.  i haven't tried reloading a webapp though, as
that is where it used to fail on 7.0.3

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org