You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by Adam Gugliciello <Ad...@skila.com> on 2001/02/17 20:17:35 UTC

Threading in a servlet architecture

Im having a significant issue with what appears to be synchronization to the
CPU of 100 concurrent threads so that each individual request is being
preformed serially, dumping the current thred stack seems to show me the
inner threads of a self referencing recursion in XPATH methods 
(usually:
"web-10" (TID:0x387c0, sys_thread_t:0x386f8, state:R, thread_t: t@46
<ma...@46> , threadID:0xf7ff1dc8, stack_bottom:0xf7ff2000,
stack_size:0x20000) prio=5
 
[1] org.apache.xalan.xpath.xml.NodeVector.addElement(NodeVector.java:106)
[2]
org.apache.xalan.xpath.MutableNodeListImpl.addNode(MutableNodeListImpl.java:
177)
[3]
org.apache.xalan.xpath.SimpleNodeLocator.addNode(SimpleNodeLocator.java:563)
[4]
org.apache.xalan.xpath.SimpleNodeLocator.findDescendants(SimpleNodeLocator.j
ava:855)
[5]
org.apache.xalan.xpath.SimpleNodeLocator.step(SimpleNodeLocator.java:363)
[6]
org.apache.xalan.xpath.SimpleNodeLocator.step(SimpleNodeLocator.java:363)
[7]
org.apache.xalan.xpath.SimpleNodeLocator.locationPath(SimpleNodeLocator.java
:316)
[8] org.apache.xalan.xpath.XPath.locationPath(XPath.java:959)
[9] org.apache.xalan.xpath.XPath.execute(XPath.java:1351)
)
the request path works like this:
 client requests page with .cmf extension, a servlet invokes and consumes a
scenario defines for the page, that scenario causes the servlet to open
loosely coupled requests to our Database access servlet which returns XML,
which is then processed according to a master xsl sheet which is specified
in the controlling scenario.. theres some other stuff in there like access
control and session management and whatnot which may also be the culprit of
the serializaion.. but the this that recently has occurred to me is this:
First, the compiliation of the XSL seems to be the bottleneck, I say this
because the threads that arent reading httpInputstreams are invariably doing
XPATH functions. fine so maybe thats so.. I've built a compiler into the
servlet that compiles the sheet into a StylesheetRoot object and stores it
in a static Hashtable for reuse after the inital usage.. all is hunky dory
with that, I see a dramatic speed increase with one user.. because most of
the system requires I be able to pass parameters into these translations I
have to use a new instance of the XSLTEngineImpl for each translation (code
follows): does reusing the same pointer to the cached Stylesheet root object
cause synchronization? is there something Im missing here? is the
XSLTEngineImpl doing anything staticly? I've taken a look at the mess of src
that comprises XALAN, and it makes my head swim. I cant even being to hunt
around in that code for this bottleneck. The reason I've started down this
path in the first place, is beacuse I've seen from CPU usage and the results
of our stress tool that the system is in fact, only processing 1 request at
any given moment, although the database seems to be chewing on the load from
them, this suggests to me that the bottleneck occurs between RDBMS access
and presentation.. 
or maybe Im wrong, any insight would help a great deal
 
                Adam
 
*/ code follows */
 
   StringReader strReader = new StringReader(inxml);
   StringWriter strWriter = new StringWriter();
    XSLTProcessor xsltprocessor =  XSLTProcessorFactory.getProcessor();
 
   if (xslfile.indexOf("?")>-1)
   {
    String paramString=xslfile.substring(xslfile.indexOf("?")+1);
    Hashtable paramsHash = HttpUtils.parseQueryString(paramString);
 
    for (Enumeration e = paramsHash.keys() ; e.hasMoreElements() ;) {
     String paramName = (String)e.nextElement();
     String paramVal =  arrayJoin((String[])paramsHash.get(paramName));
 
xsltprocessor.setStylesheetParam(paramName,xsltprocessor.createXString(param
Val));
    }
    xslfile=xslfile.substring(0,xslfile.indexOf("?"));
   }
 
   XSLTInputSource xmlsource   =  new XSLTInputSource(strReader);
   XSLTResultTarget outputsource = new XSLTResultTarget(strWriter);
 
   if (xsltStore.containsKey(xslfile) && cacheSheets &&
xsltStore.get(xslfile)!=null)
   {
         logMessage("Using precompiled sheet!");
      xsltprocessor.setStylesheet((StylesheetRoot)xsltStore.get(xslfile)); 
         xsltprocessor.process(xmlsource,null,outputsource); 
      
   }
   else
   {
    if (cacheSheets)
    {
    XSLTInputSource xslsource = new XSLTInputSource(XslRootUrl+xslfile);
           logMessage("Compiling sheet!");
    StylesheetRoot style = xsltprocessor.processStylesheet(xslsource);
          synchronized(xsltStore)
      {
       xsltStore.put(xslfile,style);
      }
           xsltprocessor.setStylesheet(style); 
           xsltprocessor.process(xmlsource,null,outputsource); 
    }
    else
    {
    XSLTInputSource xslsource = new XSLTInputSource(XslRootUrl+xslfile);
           xsltprocessor.process(xmlsource,xslsource,outputsource); 
    }
    }
 
   return (strWriter.getBuffer().toString());