[jdom-interest] possible thread issue question

Laurent Bihanic laurent.bihanic at atosorigin.com
Fri Jul 2 01:58:47 PDT 2004


Langel, Richard wrote:
> We're using 0.9, and we're seeing some strangeness which is causing us 
> problems.  We have a generic servlet that takes an xml request, converts 
> it to a Document, figures out the actual function that the user wants 
> and passes the xml off to the appropriate class to handle the request.  
> The problem we've seen is that under a stress test eventually call to 
> that servlet hangs.  It used to be the 101st call, but we increased the 
> number of available threads, the number of allowed http connections, and 
> the number of allowed client connections and the number of calls has 
> risen to about 550, but it's still happening.  Below is the function 
> we're using to make the Document.  Is there some internal configuration 
> thing we're missing or is the code below faulty?
>  
>  public Document makeDocument(String xmlInput) {
>   Document rd = null;
>   InputSource is = new InputSource(new StringReader(xmlInput));
>   SAXBuilder builder = new SAXBuilder();
>   rd = builder.build(is);
>   return rd;
>  }

Having used similar code with JDOM b9, I don't think the code above hides any 
thread locking issue.

But allocating a new SAXBuilder, hence a new XML parser instance, for every 
request is a huge waste of CPU time, especially if you are using Xerces. A 
Xerces instance is a very heavy object using many reflective calls to be build 
and holding a lot of memory, especially when using schema validation.

Check the GC profile of your application, it may spend a lot of time garbaging 
parser and JDOM objects.

JDOM b9 introduced the SAXBuilder.setParseReuse() option to allow reusing the 
XML parser instance. Yet, as neither SAXBuilder nor the XML parser are 
threadsafe, the SAXBuilder instance shall then be stored as a ThreadLocal 
object (which causes no problems as servlet containers use thread pools).

For small XML documents (< 2 KB) using schema validation, the code below 
divided the parse time by 3, allowing us to process up to 350 request/s on a 
single PIII 733Mhz machine :

     /** Thread local variable holding an XML builder instance. */
     private ThreadLocal builder = new ThreadLocal() {
             protected Object initialValue() {
                 return createBuilder();
             }
         };

     public Document makeDocument(String xmlInput)
                             throws IOException, JDOMException {
         return this.getBuilder().build(new StringReader(xmlInput));
     }

     /**
      * Returns the JDOM <code>SAXBuilder</code> associated to the
      * current thread.
      * <p>
      * If no SAXBuilder is yet associated to the current thread,
      * this implementation relies on {@link #createBuilder()} to
      * allocate and configure a new SAXBuilder.</p>
      *
      * @return the JDOM <code>SAXBuilder</code> associated to the
      *         current thread.
      */
     protected final SAXBuilder getBuilder() {
        return (SAXBuilder)(this.builder.get());
     }

     /**
      * Allocates, configures and returns a JDOM SAXBuilder object.
      *
      * @return a JDOM SAX builder.
      */
     protected SAXBuilder createBuilder() {
         // Create JDOM builder...
         SAXBuilder builder = new SAXBuilder();

         // And configure it.
         builder.setReuseParser(true);
         // builder.setIgnoringElementContentWhitespace(true);
         // etc.

         return builder;
     }

Hope this helps,

Laurent



More information about the jdom-interest mailing list