tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Denis Benoit <benoi...@sympatico.ca>
Subject [PATCH] Re: [PROPOSAL] Modification of the code generated by Jasper2
Date Tue, 30 Apr 2002 01:51:47 GMT
On Mon, 29 Apr 2002, Remy Maucherat wrote:

> This looks like a good idea to me (Kin-Man is not there this week, so it's
> not an expert opinion). I would see that kind of change going into Jasper 2,
> though. Do you think you can prepare a patch against that version ?
> 
> Remy
> 
> 
> --
> To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@jakarta.apache.org>
> For additional commands, e-mail: <mailto:tomcat-dev-help@jakarta.apache.org>
> 

Thanks!

We've done some benchmarks with JMeter, even though the case we tested is pathologic,
the JSP contained 100 tags!  The results were impressive.  The Jasper version included
with the "pre-beta" 4.1 tomcat averaged 20 seconds/hit, with the patch, the CVS
version of jasper2 average 0.8 second/hit.  If there is less try/finally nesting
in the java code of the page, the difference is less impressive of course.

The test setup, the test page and the detail of the results can be found:

	http://www3.sympatico.ca/benoitde/

NOTE my "sunday patch" contained one bug, this one has been more tested.

The patch against the CVS jasper2 is:


Index: jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java
===================================================================
RCS file: /home/cvspublic/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java,v
retrieving revision 1.6
diff -u -r1.6 Generator.java
--- jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java	25 Apr
2002 18:16:06 -0000	1.6
+++ jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java	30 Apr
2002 00:23:19 -0000
@@ -63,6 +63,8 @@
 import java.util.*;
 import java.beans.*;
 import java.net.URLEncoder;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
 import java.lang.reflect.Method;
 import javax.servlet.jsp.tagext.*;
 import org.xml.sax.Attributes;
@@ -91,6 +93,9 @@
     private JspCompilationContext ctxt;
     private boolean breakAtLF;
     private PageInfo pageInfo;
+    private FinallyApplyer finallies;
+    private int tryBit;
+    private Stack tryStack;
 
     /**
      * @param s the input string
@@ -176,6 +181,8 @@
 	    out.print  ((String)iter.next());
 	    out.println(";");
 	}
+	out.printil("import java.util.Vector;");
+	out.printil("import java.util.BitSet;");
 	out.println();
 
 	// Generate class declaration
@@ -199,6 +206,17 @@
 
 	// Constructor (empty so far) here
 	// Other methods here
+	out.printil("private void addTagToVector(Vector tags, int index, javax.servlet.jsp.tagext.Tag
tag) {");
+	out.pushIndent();
+	out.printil("if (index + 1 > tags.size())");
+	out.pushIndent();
+	out.printil("tags.setSize(index + 1);");
+	out.popIndent();
+	out.printil("tags.setElementAt(tag, index);");
+	out.popIndent();
+	out.printil("}");
+	out.println();
+	out.println();
 
 	// Now the service method
 	out.printin("public void ");
@@ -222,6 +240,8 @@
 	out.printil("ServletConfig config = null;");
 	out.printil("JspWriter out = null;");
 	out.printil("Object page = this;");
+	out.printil("BitSet bitmask = new BitSet();");
+	out.printil("Vector tags = new Vector();");
 
 	out.printil("try {");
 	out.pushIndent();
@@ -882,6 +902,10 @@
 	    out.println(" ---- */");
 
 	    Class tagHandlerClass = handlerInfo.getTagHandlerClass();
+
+	    boolean implementsTryCatchFinally =
+	            TryCatchFinally.class.isAssignableFrom(tagHandlerClass);
+
 	    out.printin(tagHandlerClass.getName());
 	    out.print(" ");
 	    out.print(tagHandlerVar);
@@ -895,8 +919,22 @@
 	    declareTagVariableInfos(tagVarInfos, n.getTagData(),
 				    VariableInfo.AT_BEGIN);
 	    
-	    out.printil("try {");
-	    out.pushIndent();
+	    if (implementsTryCatchFinally) {
+	        out.printil("try {");
+	        out.pushIndent();
+	    } else {
+	        out.printil("// try {");
+	        out.printin("bitmask.set(");
+	        Integer tryBitVal = new Integer(tryBit++);
+	        tryStack.push(tryBitVal);
+	        out.print(tryBitVal.toString());
+	        out.println(");");
+	        out.printin("addTagToVector(tags, ");
+	        out.print(tryBitVal.toString());
+	        out.print(", ");
+	        out.print(tagHandlerVar);
+	        out.println(");");
+	    }
 	    out.printin("int ");
 	    out.print(tagEvalVar);
 	    out.print(" = ");
@@ -918,8 +956,17 @@
 		out.pushIndent();
 		
 		if (isBodyTag) {
-		    out.printil("try {");
-		    out.pushIndent();
+		    out.printil("// try {");
+		    out.printin("bitmask.set(");
+		    Integer tryBitVal = new Integer(tryBit++);
+		    tryStack.push(tryBitVal);
+		    out.print(tryBitVal.toString());
+		    out.println(");");
+		    out.printin("addTagToVector(tags, ");
+		    out.print(tryBitVal.toString());
+		    out.print(", ");
+		    out.print(tagHandlerVar);
+		    out.println(");");
 		    out.printin("if (");
 		    out.print(tagEvalVar);
 		    out.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {");
@@ -981,19 +1028,35 @@
 
 	    if (n.getBody() != null) {
 		if (implementsBodyTag) {
-		    out.popIndent(); // try
+		    Integer tryBitVal = (Integer)tryStack.pop();
+		    out.printil("// } finally {");
+		    out.printin("bitmask.clear(");
+		    out.print(tryBitVal.toString());
+		    out.println(");");
+
+		    out.printin("addTagToVector(tags, ");
+		    out.print(tryBitVal.toString());
+		    out.print(", ");
+		    out.print(tagHandlerVar);
+		    out.println(");");
 
-		    out.printil("} finally {");
-		    out.pushIndent();
 		    out.printin("if (");
 		    out.print(tagEvalVar);
 		    out.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE)");
 		    out.pushIndent();
 		    out.printil("out = pageContext.popBody();");
 		    out.popIndent();
+
+		    finallies.beginPartMethod(tryBitVal.intValue());
+		    finallies.print("      if (");
+		    finallies.print("((javax.servlet.jsp.tagext.BodyTag)tags.elementAt(");
+		    finallies.print(tryBitVal.toString());
+		    finallies.print(")).doAfterBody()");
+		    finallies.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE)");
+		    finallies.println("        out = pageContext.popBody();");
 		    
-		    out.popIndent();
-		    out.printil("}");
+		    finallies.endPartMethod();
+		    out.printil("// }");
 		}
 		
 		out.popIndent(); // EVAL_BODY
@@ -1007,26 +1070,39 @@
 	    out.printil("return;");
 	    out.popIndent();
 
-	    out.popIndent(); // try
-
 	    // TryCatchFinally
 	    if (implementsTryCatchFinally) {
+		out.popIndent(); // try
+
 		out.printil("} catch (Throwable _jspx_exception) {");
 		out.pushIndent();
 		out.printin(tagHandlerVar);
 		out.println(".doCatch(_jspx_exception);");
 		out.popIndent();
-	    }
-	    out.printil("} finally {");
-	    out.pushIndent();
-	    if (implementsTryCatchFinally) {
+		out.printil("} finally {");
+		out.pushIndent();
 		out.printin(tagHandlerVar);
 		out.println(".doFinally();");
+	        out.printin(tagHandlerVar);
+	        out.println(".release();");
+	        out.popIndent();
+	        out.printil("}");
+	    } else {
+	        Integer tryBitVal = (Integer)tryStack.pop();
+	        out.printil("// } finally {");
+	        out.printin("bitmask.clear(");
+	        out.print(tryBitVal.toString());
+	        out.println(");");
+	        out.printin(tagHandlerVar);
+	        out.println(".release();");
+	        out.printil("// }");
+	        finallies.beginPartMethod(tryBitVal.intValue());
+	        finallies.printin("((javax.servlet.jsp.tagext.Tag)tags.elementAt(");
+	        finallies.print(tryBitVal.toString());
+	        finallies.print("))");
+	        finallies.println(".release();");
+	        finallies.endPartMethod();
 	    }
-	    out.printin(tagHandlerVar);
-	    out.println(".release();");
-	    out.popIndent();
-	    out.printil("}");
 
 	    // Declare and update AT_END variables
 	    updateVariableInfos(varInfos, VariableInfo.AT_END, true);
@@ -1302,7 +1378,18 @@
         out.pushIndent();
 
         // Do stuff here for finally actions...
+
+        out.printil("try {");
+        out.pushIndent();
+        out.printil("finallies(bitmask, out, tags, pageContext);");
+        out.popIndent();
+        out.printil("} catch (javax.servlet.jsp.JspException e) {");
+        out.pushIndent();
+        out.printil("if (pageContext != null) pageContext.handlePageException(e);");
+        out.popIndent();
+        out.printil("}");
         out.printil("if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);");
+
         out.popIndent();
         out.printil("}");
 
@@ -1310,6 +1397,10 @@
         out.popIndent();
         out.printil("}");
 
+        // Call the final method
+        finallies.done();
+        out.printil(finallies.toString());
+
         // Close the class definition
         out.popIndent();
         out.printil("}");
@@ -1325,6 +1416,8 @@
 	pageInfo = compiler.getPageInfo();
 	beanInfo = pageInfo.getBeanRepository();
 	breakAtLF = ctxt.getOptions().getMappedFile();
+	finallies = new FinallyApplyer();
+	tryStack = new Stack();
     }
 
     /**
@@ -1417,6 +1510,55 @@
 	 */
 	public Class getTagHandlerClass() {
 	    return tagHandlerClass;
+	}
+    }
+  
+    private static class FinallyApplyer {
+	private PrintStream finalOutput;
+	private ByteArrayOutputStream rawOutput;
+
+	FinallyApplyer() {
+	    rawOutput = new ByteArrayOutputStream();
+	    finalOutput = new PrintStream(rawOutput, true);
+
+	    finalOutput.println();
+	    finalOutput.println("  private void finallies(BitSet bitmask, JspWriter out, Vector
tags, PageContext pageContext)");
+	    finalOutput.println("  throws javax.servlet.jsp.JspException {");
+	}
+
+	public void done() {
+	    finalOutput.println("  }");
+	}
+
+	public void beginPartMethod(int bit) {
+	    finalOutput.print("    if (bitmask.get(");
+	    finalOutput.print(bit);
+	    finalOutput.println(")) {");
+	}
+
+	public void endPartMethod() {
+	    finalOutput.println("    }");
+	    finalOutput.println();
+	}
+
+	public void println(String aLine) {
+	    if (null != aLine) {
+	        finalOutput.print(aLine);
+	    }
+	    finalOutput.println();
+	}
+
+	public void printin(String partLine) {
+	    finalOutput.print("      ");
+	    finalOutput.print(partLine);
+	}
+
+	public void print(String partLine) {
+	    finalOutput.print(partLine);
+	}
+
+	public String toString() {
+	    return rawOutput.toString();
 	}
     }
 }


--
To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:tomcat-dev-help@jakarta.apache.org>


Mime
View raw message