igorh       2004/05/06 08:31:28

  Modified:    java/src/org/apache/xalan/templates AVT.java
  Log:
  The problem is that we use an object pool (shared between different threads)
  to allocate  FastStringBuffer objects. The problem results in a serious 
performance
  degradation  on Z/OS and seems to be invisible on AIX.
  
  1 Differences in optimization of object pools  for different JVMs and for 
different 
  platforms are known(I know it now too). It is not surprising that  Z/OS and 
AIX 
  have different results.
  
  2. 
  a. Object pools should be used only for very heavy object which live for a 
long time
  and could be reused in a lot of places. 
  b. Small local objects which size cannot be changed could be allocated on the
  stack => creating them with new in the local scope could be a good idea.
  c. Caching middle size objects which can grow in size seems as a good idea,
  because such objects usually cannot be allocated on the stack.
   This is actually the case for FastStringBuffer objects. 
  
   Solution
  I am creating FastStringBuffer objects in a local scope. I am going
  to use caching whenever possible. 
  First I am fixing the bug. 
  
  Revision  Changes    Path
  1.24      +90 -67    xml-xalan/java/src/org/apache/xalan/templates/AVT.java
  
  Index: AVT.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/AVT.java,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- AVT.java  28 Apr 2004 21:59:28 -0000      1.23
  +++ AVT.java  6 May 2004 15:31:28 -0000       1.24
  @@ -37,7 +37,25 @@
    */
   public class AVT implements java.io.Serializable, XSLTVisitable
   {
  -
  +  
  +  /**
  +    *We are not going to use the object pool if USE_OBJECT_POOL == false.
  +  */
  +  private final static boolean USE_OBJECT_POOL = false; 
  +  
  +  /**
  +    * INIT_BUFFER_CHUNK_BITS is used to set initial size of
  +    * of the char m_array in FastStringBuffer if USE_OBJECT_POOL == false. 
  +    * size = 2^ INIT_BUFFER_CHUNK_BITS, INIT_BUFFER_CHUNK_BITS = 7 
  +    * corresponds size = 256. 
  +  */
  +  private final static int INIT_BUFFER_CHUNK_BITS = 8; 
  +  
  +  /**
  +   * We are caching FastStringBuffer objects if if USE_OBJECT_POOL == false
  +   */
  +  private transient FastStringBuffer m_cachedBuf;
  +  
     /**
      * If the AVT is not complex, just hold the simple string.
      * @serial
  @@ -49,6 +67,8 @@
      * @serial
      */
     private Vector m_parts = null;
  +  
  +   
   
     /**
      * The name of the attribute.
  @@ -161,9 +181,15 @@
       }
       else
       {
  -      FastStringBuffer buffer = StringBufferPool.get();
  -      FastStringBuffer exprBuffer = StringBufferPool.get();
  -
  +      FastStringBuffer buffer = null;
  +      FastStringBuffer exprBuffer = null;
  +      if(USE_OBJECT_POOL){
  +        buffer = StringBufferPool.get(); 
  +        exprBuffer = StringBufferPool.get();
  +      }else{
  +        buffer = new FastStringBuffer(6);
  +        exprBuffer = new FastStringBuffer(6);
  +      }
         try
         {
           m_parts = new Vector(nTokens + 1);
  @@ -395,8 +421,13 @@
         }
         finally
         {
  -        StringBufferPool.free(buffer);
  -        StringBufferPool.free(exprBuffer);
  +        if(USE_OBJECT_POOL){
  +             StringBufferPool.free(buffer);
  +             StringBufferPool.free(exprBuffer);
  +         }else{
  +            buffer = null;
  +            exprBuffer = null;
  +         };
         }
       }  // end else nTokens > 1
   
  @@ -416,42 +447,32 @@
     public String getSimpleString()
     {
   
  -    if (null != m_simpleString)
  -    {
  +    if (null != m_simpleString){
         return m_simpleString;
       }
  -    else if (null != m_parts)
  -    {
  -      FastStringBuffer buf = StringBufferPool.get();
  -      String s;
  -
  -      try
  -      {
  -        buf.setLength(0);
  -
  -        int n = m_parts.size();
  -
  -        for (int i = 0; i < n; i++)
  -        {
  -          AVTPart part = (AVTPart) m_parts.elementAt(i);
  -
  -          buf.append(part.getSimpleString());
  -        }
  -
  -        s = buf.toString();
  -      }
  -      finally
  -      {
  -        StringBufferPool.free(buf);
  +    else if (null != m_parts){
  +     final FastStringBuffer buf = getBuffer();
  +     String out = null;
  +
  +    int n = m_parts.size();
  +    try{
  +      for (int i = 0; i < n; i++){
  +        AVTPart part = (AVTPart) m_parts.elementAt(i);
  +        buf.append(part.getSimpleString());
         }
  -
  -      return s;
  +      out = buf.toString();
  +    }finally{
  +      if(USE_OBJECT_POOL){
  +         StringBufferPool.free(buf);
  +     }else{
  +        buf.setLength(0); 
  +     };
       }
  -    else
  -    {
  +    return out;
  +  }else{
         return "";
  -    }
     }
  +}
   
     /**
      * Evaluate the AVT and return a String.
  @@ -469,39 +490,28 @@
             XPathContext xctxt, int context, 
org.apache.xml.utils.PrefixResolver nsNode)
               throws javax.xml.transform.TransformerException
     {
  -
  -    if (null != m_simpleString)
  -    {
  -            return m_simpleString;
  -    }
  -    
  -    FastStringBuffer buf = null;
  -    try
  -    {
  -      buf = StringBufferPool.get();
  -      if (null != m_parts)
  -      {
  -        buf.setLength(0);
  -
  -        int n = m_parts.size();
  -
  -        for (int i = 0; i < n; i++)
  -        {
  -          AVTPart part = (AVTPart) m_parts.elementAt(i);
  -
  +    if (null != m_simpleString){
  +        return m_simpleString;
  +    }else if (null != m_parts){
  +      final FastStringBuffer buf =getBuffer();
  +      String out = null;
  +      int n = m_parts.size();
  +      try{
  +        for (int i = 0; i < n; i++){
  +          AVTPart part = (AVTPart) m_parts.elementAt(i);  
             part.evaluate(xctxt, buf, context, nsNode);
           }
  -
  -        return buf.toString();
  +       out = buf.toString();
  +      }finally{
  +          if(USE_OBJECT_POOL){
  +             StringBufferPool.free(buf);
  +         }else{
  +           buf.setLength(0); 
  +         }
         }
  -      else
  -      {
  -        return "";
  -      }
  -    }finally{
  -      if(buf != null){
  -        StringBufferPool.free(buf);
  -      }      
  +     return out;
  +    }else{
  +      return "";
       }
     }
   
  @@ -595,5 +605,18 @@
      */
     public boolean isSimple() {
        return m_simpleString != null;
  +  }
  +  
  +  private final FastStringBuffer getBuffer(){
  +    if(USE_OBJECT_POOL){
  +       return StringBufferPool.get();
  +    }else if(m_cachedBuf == null){
  +       m_cachedBuf = new FastStringBuffer(INIT_BUFFER_CHUNK_BITS);
  +       return m_cachedBuf;
  +    }else if(m_cachedBuf.length() != 0){
  +      return new FastStringBuffer(INIT_BUFFER_CHUNK_BITS);
  +    }else{
  +       return m_cachedBuf;
  +     }
     }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to