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]