mrglavas    2004/10/20 20:40:43

  Modified:    java/src/org/apache/xerces/impl XMLEntityManager.java
  Log:
  Reduce overhead of creating a ScannedEntity by reusing

  character buffers. This is accomplished with a buffer pool.

  Buffers are returned to the pool once scanning of the

  entity is complete. Also reducing the internal entity buffer

  size to 512 from 1024.

  

  XMLEntityManager$ScannedEntity creation time: 

  Xerces 2.6.2 :  0.8 sec for 674 invocations (avg) 

  New              :  0.02 sec for 674 invocations (avg) 

  

  That translates to a 7-9% improvement in the overall

  speed of parsing. This performance improvement is

  thanks to the patch by Ankit Pasricha.
  
  Revision  Changes    Path
  1.91      +121 -6    xml-xerces/java/src/org/apache/xerces/impl/XMLEntityManager.java
  
  Index: XMLEntityManager.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xerces/java/src/org/apache/xerces/impl/XMLEntityManager.java,v
  retrieving revision 1.90
  retrieving revision 1.91
  diff -u -r1.90 -r1.91
  --- XMLEntityManager.java     20 Oct 2004 22:23:40 -0000      1.90
  +++ XMLEntityManager.java     21 Oct 2004 03:40:43 -0000      1.91
  @@ -16,19 +16,19 @@
   
   package org.apache.xerces.impl;
   
  -import java.lang.reflect.Method;
   import java.io.IOException;
   import java.io.InputStream;
   import java.io.InputStreamReader;
   import java.io.Reader;
   import java.io.StringReader;
  +import java.lang.reflect.Method;
   import java.net.HttpURLConnection;
   import java.net.URL;
   import java.net.URLConnection;
   import java.util.Hashtable;
   import java.util.Iterator;
  -import java.util.Map;
   import java.util.Locale;
  +import java.util.Map;
   import java.util.Stack;
   
   import org.apache.xerces.impl.io.ASCIIReader;
  @@ -93,8 +93,8 @@
       /** Default buffer size before we've finished with the XMLDecl:  */
       public static final int DEFAULT_XMLDECL_BUFFER_SIZE = 64;
   
  -    /** Default internal entity buffer size (1024). */
  -    public static final int DEFAULT_INTERNAL_BUFFER_SIZE = 1024;
  +    /** Default internal entity buffer size (512). */
  +    public static final int DEFAULT_INTERNAL_BUFFER_SIZE = 512;
   
       // feature identifiers
   
  @@ -349,6 +349,9 @@
       
       /** Augmentations for entities. */
       private final Augmentations fEntityAugs = new AugmentationsImpl();
  +    
  +    /** Pool of character buffers. */
  +    private CharacterBufferPool fBufferPool = new CharacterBufferPool(fBufferSize, 
DEFAULT_INTERNAL_BUFFER_SIZE);
   
       //
       // Constructors
  @@ -1408,6 +1411,7 @@
                       bufferSize.intValue() > DEFAULT_XMLDECL_BUFFER_SIZE) {
                       fBufferSize = bufferSize.intValue();
                       fEntityScanner.setBufferSize(fBufferSize);
  +                    fBufferPool.setExternalBufferSize(fBufferSize);
                   }
               }
               if (suffixLength == Constants.SECURITY_MANAGER_PROPERTY.length() && 
  @@ -1778,6 +1782,9 @@
               fReaderStack.pop();
           } 
   
  +        //Release the character buffer back to the pool for reuse
  +        fBufferPool.returnToPool(fCurrentEntity.fBuffer);
  +        
           // Pop entity stack.
           fCurrentEntity = fEntityStack.size() > 0
                          ? (ScannedEntity)fEntityStack.pop() : null;
  @@ -2418,6 +2425,10 @@
   
           // to allow the reader/inputStream to behave efficiently:
           public boolean mayReadChunks;
  +        
  +        /** Character buffer container. */
  +        private CharacterBuffer fBuffer;
  +        
   
           //
           // Constructors
  @@ -2436,7 +2447,8 @@
               this.literal = literal;
               this.mayReadChunks = mayReadChunks;
               this.isExternal = isExternal;
  -            this.ch = new char[isExternal ? fBufferSize : 
DEFAULT_INTERNAL_BUFFER_SIZE];
  +            this.fBuffer = fBufferPool.getBuffer(isExternal);
  +            this.ch = fBuffer.ch;
           } // <init>(StringXMLResourceIdentifier,InputStream,Reader,String,boolean, 
boolean)
   
           //
  @@ -2591,6 +2603,109 @@
           } // toString():String
   
       } // class ScannedEntity
  +    
  +    /**
  +     * Buffer used in entity manager to reuse character arrays instead
  +     * of creating new ones every time.
  +     * 
  +     * @xerces.internal
  +     * 
  +     * @author Ankit Pasricha, IBM
  +     */
  +    private static class CharacterBuffer {
  +
  +        /** character buffer */
  +        private char[] ch;
  +        
  +        /** whether the buffer is for an external or internal scanned entity */
  +        private boolean isExternal;
  +        
  +        public CharacterBuffer(boolean isExternal, int size) {
  +            this.isExternal = isExternal;
  +            ch = new char[size];
  +        }
  +    }
  +    
  +    /**
  +     * Stores a number of character buffers and provides it to the entity
  +     * manager to use when an entity is seen.
  +     * 
  +     * @xerces.internal 
  +     * 
  +     * @author Ankit Pasricha, IBM
  +     */
  +    private static class CharacterBufferPool {
  +
  +        private static final int DEFAULT_POOL_SIZE = 3;
  +        
  +        private CharacterBuffer[] fInternalBufferPool;
  +        private CharacterBuffer[] fExternalBufferPool;
  +
  +        private int fExternalBufferSize;
  +        private int fInternalBufferSize;
  +        private int poolSize;
  +        
  +        private int fInternalTop;
  +        private int fExternalTop;
  +
  +        public CharacterBufferPool(int externalBufferSize, int internalBufferSize) {
  +            this(DEFAULT_POOL_SIZE, externalBufferSize, internalBufferSize);
  +        }
  +        
  +        public CharacterBufferPool(int poolSize, int externalBufferSize, int 
internalBufferSize) {
  +            fExternalBufferSize = externalBufferSize;
  +            fInternalBufferSize = internalBufferSize;
  +            this.poolSize = poolSize;
  +            init();
  +        }
  +        
  +        /** Initializes buffer pool. **/
  +        private void init() {
  +            fInternalBufferPool = new CharacterBuffer[poolSize];
  +            fExternalBufferPool = new CharacterBuffer[poolSize];
  +            fInternalTop = -1;
  +            fExternalTop = -1;
  +        }
  +
  +        /** Retrieves buffer from pool. **/
  +        public CharacterBuffer getBuffer(boolean external) {
  +            if (external) {
  +                if (fExternalTop > -1) {
  +                    return (CharacterBuffer)fExternalBufferPool[fExternalTop--];
  +                }
  +                else {
  +                    return new CharacterBuffer(true, fExternalBufferSize);
  +                }
  +            }
  +            else {
  +                if (fInternalTop > -1) {
  +                    return (CharacterBuffer)fInternalBufferPool[fInternalTop--];
  +                }
  +                else {
  +                    return new CharacterBuffer(false, fInternalBufferSize);
  +                }
  +            }
  +        }
  +        
  +        /** Returns buffer to pool. **/
  +        public void returnToPool(CharacterBuffer buffer) {
  +            if (buffer.isExternal) {
  +                if (fExternalTop < fExternalBufferPool.length - 1) {
  +                    fExternalBufferPool[++fExternalTop] = buffer;
  +                }
  +            }
  +            else if (fInternalTop < fInternalBufferPool.length - 1) {
  +                fInternalBufferPool[++fInternalTop] = buffer;
  +            }
  +        }
  +
  +        /** Sets the size of external buffers and dumps the old pool. **/
  +        public void setExternalBufferSize(int bufferSize) {
  +            fExternalBufferSize = bufferSize;
  +            fExternalBufferPool = new CharacterBuffer[poolSize];
  +            fExternalTop = -1;
  +        }
  +    }
   
       /**
        * This class wraps the byte inputstreams we're presented with.
  
  
  

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

Reply via email to