Hi, Florian
There are a few suspected areas, but we don't have the complicated
environment to test. If you would like to help, I can send you a patched
xalan.jar to test in your setup. We can have more ideas about the nature
of the problem from the test results in your environment.
Thanks.
Morris Kwan
XSLT Development
IBM Toronto Lab
Tel: (905)413-3729
Email: [EMAIL PROTECTED]
"Florian
Deissenboeck" To: Morris
Kwan/Toronto/[EMAIL PROTECTED]
<[EMAIL PROTECTED] cc: <[EMAIL PROTECTED]>
.de> Subject: RE: Tomcat
out-of-memory-error when caching XSLT
11/28/2002 06:15
AM
Hi,
1. Looks like 2.4.0 is used:
#---- BEGIN writeEnvironmentReport($Revision: 1.13 $): Useful stuff
found: ---- version.DOM.draftlevel=2.0fd
java.class.path=C:\jakarta-tomcat-4.0.3\bin\bootstrap.jar version.JAXP=1.1
java.ext.dirs=C:\j2sdk1.4.0\jre\lib\ext #---- BEGIN Listing XML-related
jars
in: foundclasses.sun.boot.class.path ----
xalan.jar-apparent.version=xalan.jar from xalan-j_2_4_0
xalan.jar-path=C:\j2sdk1.4.0\jre\lib\endorsed\xalan.jar #----- END Listing
XML-related jars in: foundclasses.sun.boot.class.path -----
version.xerces2=Xerces-J 2.1.0 version.xerces1=not-present
version.xalan2_2=Xalan Java 2.4.0 version.xalan1=not-present
version.ant=not-present java.version=1.4.0 version.DOM=2.0
version.crimson=present-unknown-version
sun.boot.class.path=C:\j2sdk1.4.0\jre\lib\endorsed\xalan.jar;C:
\j2sdk1.4.0\j
re\lib\rt.jar;C:\j2sdk1.4.0\jre\lib\i18n.jar;C:
\j2sdk1.4.0\jre\lib\sunrsasig
n.jar;C:\j2sdk1.4.0\jre\lib\jsse.jar;C:\j2sdk1.4.0\jre\lib\jce.jar;C:
\j2sdk1
.4.0\jre\lib\charsets.jar;C:\j2sdk1.4.0\jre\classes version.SAX=2.0
version.xalan2x=Xalan Java 2.4.0 #----- END writeEnvironmentReport: Useful
properties found: ----- # YAHOO! Your environment seems to be OK.
2. It's one stylesheet including 8 other stylesheet, all in all about 2000
lines of XSLT.
3. We did the tests with JMeter and configured 30 threads. After ~300
requests the server dies. If we do the test with a single user (thread)
only
there seem to be no problems. At least the server survives 5000 sequential
requests. We also did a test with 3 concurrent users which went well, too.
I
I guess concurrency is the problem, otherwise the single user test should
fail, too.
Thanks,
Flo
> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
> Sent: Mittwoch, 27. November 2002 17:37
> To: Florian Deissenboeck
> Cc: [EMAIL PROTECTED]
> Subject: Re: Tomcat out-of-memory-error when caching XSLT
>
>
> Hi, Florian
>
> We could have a better idea if I can provide the following information:
>
> 1. Are you sure Tomcat is picking up Xalan 2.4.0 rather than JDK 1.4's
> builtin Xalan (2.2.D11)? If not sure, you can use EnvironmentCheck to
find
> it out.
> 2. How many stylesheets (.xsl files) do you have?
> 3. Did all the requests run concurrently in different threads or
> sequentially in one thread?
>
> Morris Kwan
> XSLT Development
> IBM Toronto Lab
> Tel: (905)413-3729
> Email: [EMAIL PROTECTED]
>
>
>
>
>
> "Florian
>
> Deissenboeck" To:
> <[EMAIL PROTECTED]>
> <[EMAIL PROTECTED] cc:
>
> .de> Subject: Tomcat
> out-of-memory-error when caching XSLT
>
>
> 11/27/2002 09:55
>
> AM
>
>
>
>
>
>
>
>
> Hi,
>
> Tomcat dies with a java.lang.OutOfMemoryError if we cache stylesheets and
> more than ~10 users access server simultaneously. The details:
>
> We have simple servlet which does triggers XSLT transformation. The input
> XML has ~50 lines, the XSLT has ~2000 lines. We did a load test
> with Apache
> JMeter simulating 30 users accessing the server more or less
> simultaneously.
> If we do no caching at all the server survives but performance is poor.
So
> we wrote a small caching class which is very similar to the one presented
> in
> O'Reilly's "Java and XSLT"-Book. It uses a hashmap for template
> caching, I
> attached class.
>
> We first tried to use XSLTC
> (transformerFactory = (new
> org.apache.xalan.xsltc.trax.TransformerFactoryImpl()).newInstance();).
> Performance increases rapidly but the server runs out of memory after
~300
> accesses. Everything is ok for 1 to ~10 users. So we tried the classic
> template thing
> (transformerFactory =(new
> org.apache.xalan.processor.TransformerFactoryImpl()).newInstance();).
> Performance is worse than XSLTC but much better than no cache.
> Unfortunately
> we have exactly the same memory problem as with XSLTC.
>
> The specs of our environment: Server: Pentium III, 850 Mhz, 256 MB RAM,
> Windows 2000, JDK 1.4, Tomcat 4.0.3, Xalan 2.4.0
>
> As far as I understand the templates interface it should be much more
> memory
> efficient to cache the stylesheets than doing transformation without
> caching. We would be really glad if someone has an idea what could be
> wrong.
> A bug in the cache? A bug in Tomcat, Xalan? To big stylesheets?
>
> Thanks in advance,
>
> Flo
>
> --------------
> Stylesheet cache:
>
> package edu.tum.cs.olev;
>
> import java.util.HashMap;
> import java.util.Date;
> import java.util.Collection;
> import java.util.Set;
>
> import java.text.DecimalFormat;
>
> import java.io.File;
>
> import javax.xml.transform.Templates;
> import javax.xml.transform.Transformer;
> import javax.xml.transform.TransformerConfigurationException;
> import javax.xml.transform.TransformerFactory;
> import javax.xml.transform.stream.StreamSource;
>
> /**
> * This class implements a XSLT stylesheet cache. Since this class is NOT
> thread-safe, methods
> * must not be called by any object except the
> <code>Config</code>-singleton.
> * Again: Although all methods are explained they are not supposed to be
> called from any class
> * other than <code>Config</code>. <code>Config</code> provides methods
to
> access all features
> * of the cache.<br />
> * This class is based on <code>StylesheetCache.java</code> from "Java
and
> XSLT" by Eric M. Burke
> * (O'Reilly).
> * @see Config
> * @version $Revision: 1.5 $, Date: $Date: 2002/10/13 17:09:36 $
> * @author $Author: deissenb $
> * @author ‹-- last modification | A. Freyschmidt, F. Deissenboeck,
> S.
> Winter
> */
> public class XSLTCache {
> /** counts cache hits */
> private double cacheHits=0;
>
> /** counts requests */
> private double requests=0;
>
> /** the actual cache */
> private HashMap cache = new HashMap();
>
> /** time of last flus */
> private Date lastFlushed;
>
> private TransformerFactory transformerFactory;
>
> protected XSLTCache() {
> //XSLTC
> //transformerFactory =
> // (new
> org.apache.xalan.xsltc.trax.TransformerFactoryImpl()).newInstance();
>
> //classic
> transformerFactory =
> (new
> org.apache.xalan.processor.TransformerFactoryImpl()).newInstance();
> }
>
> /**
> * Flushes the whole cache.
> */
> private void flushAll() {
> requests = 0;
> cacheHits = 0;
> cache.clear();
> lastFlushed = new Date();
> }
>
> /**
> * This is the method to obtain a cached version of a stylesheet. If no
> cached version is present
> * this method sets up a new <code>Transformer</code>. The method uses
> the
> <code>Templates</code>-
> * interface for stylesheet caching. <br />
> * @param xsltFilename the filename of the stylesheet. The
> method expects
> the pure filename without
> * any path information
> * @return a <code>Transfomer</code>
> * @throws TransformerConfigurationException
> */
> protected Transformer getTransformer(String xsltFilename)
> throws TransformerConfigurationException {
>
> //increase hits
> requests++;
>
> //increase hits in every case
> cacheHits++;
>
> //store XSLT
> File xslt = new File(Config.getInstance().getXSLTPath(xsltFilename));
>
> //get entry from cache
> Templates entry = (Templates)cache.get(xsltFilename);
>
> //we don't have cached version
> if (entry == null) {
> //this is no cache hit
> cacheHits--;
>
> StreamSource source = new StreamSource(xslt);
>
> entry = transformerFactory.newTemplates(source);
>
> //store it in the cache
> cache.put(xsltFilename, entry);
> }
>
> //now we have entry anyway, get the Transformer
> return entry.newTransformer();
>
> }
>
> /**
> * This method returns a string containing minimal status information
> about the cache.
> * The information string look like this<br />
> * <code>Cache info: Requests: 8.0, Hits: 5.0, Ratio: 0,62, #
> entries: 3,
> * last flush: Tue Oct 08 18:34:06 CEST 2002</code>
> * @return the information string
> */
> protected String getCacheInfo() {
> DecimalFormat format = new DecimalFormat("0.00");
> String info = "Cache info: Requests: " + requests + ", Hits: " +
> cacheHits + ", Ratio: " + format.format(cacheHits/requests)
> + ", # entries: " + cache.size() + ", last flush: " + lastFlushed;
> return info;
> }
>
> /**
> * Returns the names of all cache entries (the file names)
> */
> protected Set getEntryNames() {
> return cache.keySet();
> }
>
> }
>
>
>
>