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]