You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ga...@apache.org on 2012/12/10 22:20:21 UTC
svn commit: r1419776 - in
/geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler:
JspReader.java Mark.java
Author: gawor
Date: Mon Dec 10 21:20:20 2012
New Revision: 1419776
URL: http://svn.apache.org/viewvc?rev=1419776&view=rev
Log:
Performance tuning solution for JspReader - https://issues.apache.org/bugzilla/show_bug.cgi?id=53713
Modified:
geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/JspReader.java
geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/Mark.java
Modified: geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/JspReader.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/JspReader.java?rev=1419776&r1=1419775&r2=1419776&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/JspReader.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/JspReader.java Mon Dec 10 21:20:20 2012
@@ -193,6 +193,65 @@ class JspReader {
}
/**
+ * A faster approach than calling {@link #mark()} & {@link #nextChar()}.
+ * However, this approach is only safe if the mark is only used within the
+ * JspReader.
+ */
+ private int nextChar(Mark mark) throws JasperException {
+ if (!hasMoreInput()) {
+ return -1;
+ }
+
+ int ch = current.stream[current.cursor];
+
+ mark.init(current, singleFile);
+
+ current.cursor++;
+
+ if (ch == '\n') {
+ current.line++;
+ current.col = 0;
+ } else {
+ current.col++;
+ }
+ return ch;
+ }
+
+ /**
+ * Search the given character, If it was found, then mark the current cursor
+ * and the cursor point to next character.
+ */
+ private Boolean indexOf(char c, Mark mark) throws JasperException {
+ if (!hasMoreInput())
+ return null;
+
+ int end = current.stream.length;
+ int ch;
+ int line = current.line;
+ int col = current.col;
+ int i = current.cursor;
+ for(; i < end; i ++) {
+ ch = current.stream[i];
+
+ if (ch == c) {
+ mark.update(i, line, col);
+ }
+ if (ch == '\n') {
+ line++;
+ col = 0;
+ } else {
+ col++;
+ }
+ if (ch == c) {
+ current.update(i+1, line, col);
+ return Boolean.TRUE;
+ }
+ }
+ current.update(i, line, col);
+ return Boolean.FALSE;
+ }
+
+ /**
* Back up the current cursor by one char, assumes current.cursor > 0,
* and that the char to be pushed back is not '\n'.
*/
@@ -205,10 +264,11 @@ class JspReader {
Mark oldstart = mark();
reset(start);
CharArrayWriter caw = new CharArrayWriter();
- while (!stop.equals(mark()))
+ while (!markEquals(stop)) {
caw.write(nextChar());
+ }
caw.close();
- reset(oldstart);
+ setCurrent(oldstart);
return caw.toString();
}
@@ -222,11 +282,27 @@ class JspReader {
return new Mark(current);
}
+
+ /**
+ * This method avoids a call to {@link #mark()} when doing comparison.
+ */
+ private boolean markEquals(Mark another) {
+ return another.equals(current);
+ }
+
void reset(Mark mark) {
current = new Mark(mark);
}
/**
+ * Similar to {@link #reset(Mark)} but no new Mark will be created.
+ * Therefore, the parameter mark must NOT be used in other places.
+ */
+ private void setCurrent(Mark mark) {
+ current = mark;
+ }
+
+ /**
* search the stream for a match to a string
* @param string The string to match
* @return <strong>true</strong> is one is found, the current position
@@ -234,17 +310,40 @@ class JspReader {
* false</strong> otherwise, position in stream unchanged.
*/
boolean matches(String string) throws JasperException {
- Mark mark = mark();
- int ch = 0;
- int i = 0;
- do {
- ch = nextChar();
- if (((char) ch) != string.charAt(i++)) {
- reset(mark);
- return false;
- }
- } while (i < string.length());
- return true;
+ int len = string.length();
+ int cursor = current.cursor;
+ int streamSize = current.stream.length;
+ if (cursor + len < streamSize) { //Try to scan in memory
+ int line = current.line;
+ int col = current.col;
+ int ch;
+ int i = 0;
+ for(; i < len; i ++) {
+ ch = current.stream[i+cursor];
+ if (string.charAt(i) != ch) {
+ return false;
+ }
+ if (ch == '\n') {
+ line ++;
+ col = 0;
+ } else {
+ col++;
+ }
+ }
+ current.update(i+cursor, line, col);
+ } else {
+ Mark mark = mark();
+ int ch = 0;
+ int i = 0;
+ do {
+ ch = nextChar();
+ if (((char) ch) != string.charAt(i++)) {
+ setCurrent(mark);
+ return false;
+ }
+ } while (i < len);
+ }
+ return true;
}
boolean matchesETag(String tagName) throws JasperException {
@@ -256,7 +355,7 @@ class JspReader {
if (nextChar() == '>')
return true;
- reset(mark);
+ setCurrent(mark);
return false;
}
@@ -271,7 +370,7 @@ class JspReader {
if (nextChar() == '>')
return true;
- reset(mark);
+ setCurrent(mark);
return false;
}
@@ -290,7 +389,7 @@ class JspReader {
skipSpaces();
boolean result = matches( s );
if( !result ) {
- reset( mark );
+ setCurrent(mark);
}
return result;
@@ -315,24 +414,29 @@ class JspReader {
* otherwise.
*/
Mark skipUntil(String limit) throws JasperException {
- Mark ret = null;
+ Mark ret = mark();
int limlen = limit.length();
- int ch;
+ char firstChar = limit.charAt(0);
+ Boolean result = null;
+ Mark restart = null;
skip:
- for (ret = mark(), ch = nextChar() ; ch != -1 ;
- ret = mark(), ch = nextChar()) {
- if (ch == limit.charAt(0)) {
- Mark restart = mark();
- for (int i = 1 ; i < limlen ; i++) {
- if (peekChar() == limit.charAt(i))
- nextChar();
- else {
- reset(restart);
- continue skip;
- }
- }
- return ret;
+ while((result = indexOf(firstChar, ret)) != null) {
+ if (result.booleanValue()) {
+ if (restart != null) {
+ restart.init(current, singleFile);
+ } else {
+ restart = mark();
+ }
+ for (int i = 1 ; i < limlen ; i++) {
+ if (peekChar() == limit.charAt(i)) {
+ nextChar();
+ } else {
+ current.init(restart, singleFile);
+ continue skip;
+ }
+ }
+ return ret;
}
}
return null;
@@ -349,18 +453,16 @@ class JspReader {
* otherwise.
*/
Mark skipUntilIgnoreEsc(String limit) throws JasperException {
- Mark ret = null;
+ Mark ret = mark();
int limlen = limit.length();
int ch;
int prev = 'x'; // Doesn't matter
-
+ char firstChar = limit.charAt(0);
skip:
- for (ret = mark(), ch = nextChar() ; ch != -1 ;
- ret = mark(), prev = ch, ch = nextChar()) {
+ for (ch = nextChar(ret) ; ch != -1 ; prev = ch, ch = nextChar(ret)) {
if (ch == '\\' && prev == '\\') {
ch = 0; // Double \ is not an escape char anymore
- }
- else if (ch == limit.charAt(0) && prev != '\\') {
+ } else if (ch == firstChar && prev != '\\') {
for (int i = 1 ; i < limlen ; i++) {
if (peekChar() == limit.charAt(i))
nextChar();
@@ -477,10 +579,10 @@ class JspReader {
Mark mark = mark();
if (((ch = nextChar()) == '>')
|| ((ch == '-') && (nextChar() == '>'))) {
- reset(mark);
+ setCurrent(mark);
return true;
} else {
- reset(mark);
+ setCurrent(mark);
return false;
}
}
Modified: geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/Mark.java
URL: http://svn.apache.org/viewvc/geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/Mark.java?rev=1419776&r1=1419775&r2=1419776&view=diff
==============================================================================
--- geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/Mark.java (original)
+++ geronimo/external/trunk/tomcat-parent-7.0.27/jasper/src/main/java/org/apache/jasper/compiler/Mark.java Mon Dec 10 21:20:20 2012
@@ -89,22 +89,37 @@ final class Mark {
* Constructor
*/
Mark(Mark other) {
+ init(other, false);
+ }
+
+ void update(int cursor, int line, int col) {
+ this.cursor = cursor;
+ this.line = line;
+ this.col = col;
+ }
- this.reader = other.reader;
- this.ctxt = other.reader.getJspCompilationContext();
- this.stream = other.stream;
- this.fileId = other.fileId;
- this.fileName = other.fileName;
+ void init(Mark other, boolean singleFile) {
this.cursor = other.cursor;
this.line = other.line;
this.col = other.col;
- this.baseDir = other.baseDir;
- this.encoding = other.encoding;
- // clone includeStack without cloning contents
- includeStack = new Stack<IncludeState>();
- for ( int i=0; i < other.includeStack.size(); i++ ) {
- includeStack.addElement( other.includeStack.elementAt(i) );
+ if (!singleFile) {
+ this.reader = other.reader;
+ this.ctxt = other.ctxt;
+ this.stream = other.stream;
+ this.fileId = other.fileId;
+ this.fileName = other.fileName;
+ this.baseDir = other.baseDir;
+ this.encoding = other.encoding;
+
+ if (includeStack == null) {
+ includeStack = new Stack<IncludeState>();
+ } else {
+ includeStack.clear();
+ }
+ for (int i = 0; i < other.includeStack.size(); i++ ) {
+ includeStack.addElement(other.includeStack.elementAt(i));
+ }
}
}