Author: kkolinko Date: Thu Mar 15 18:14:44 2012 New Revision: 1301123 URL: http://svn.apache.org/viewvc?rev=1301123&view=rev Log: Slightly improve performance of UDecoder Backports r1203054 from 7.0.x.
- Reduce overhead from exception handling, using ProxyDirContext.NOT_FOUND_EXCEPTION as an example. - Limit second string scan using results from the first one. The s/findByte()/indexOf()/ change part of r1203054 has not been backported. Modified: tomcat/tc6.0.x/trunk/STATUS.txt tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Modified: tomcat/tc6.0.x/trunk/STATUS.txt URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=1301123&r1=1301122&r2=1301123&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/STATUS.txt (original) +++ tomcat/tc6.0.x/trunk/STATUS.txt Thu Mar 15 18:14:44 2012 @@ -69,12 +69,6 @@ PATCHES PROPOSED TO BACKPORT: +1: kkolinko, rjung, fhanik -1: -* Reduce overhead from exception handling in UDecoder - http://people.apache.org/~kkolinko/patches/2011-11-17_tc6_UDecoder.patch - (r1203054 in TC7) - +1: kkolinko,funkman, fhanik - -1: - * Align %2f handling between implementations of UDecoder.convert() http://svn.apache.org/viewvc?rev=1203091&view=rev +1: kkolinko,funkman, fhanik Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java?rev=1301123&r1=1301122&r2=1301123&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/buf/UDecoder.java Thu Mar 15 18:14:44 2012 @@ -33,6 +33,30 @@ public final class UDecoder { protected static final boolean ALLOW_ENCODED_SLASH = Boolean.valueOf(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "false")).booleanValue(); + private static class DecodeException extends CharConversionException { + private static final long serialVersionUID = 1L; + public DecodeException(String s) { + super(s); + } + + @Override + public synchronized Throwable fillInStackTrace() { + // This class does not provide a stack trace + return this; + } + } + + /** Unexpected end of data. */ + private static final IOException EXCEPTION_EOF = new DecodeException("EOF"); + + /** %xx with not-hex digit */ + private static final IOException EXCEPTION_NOT_HEX_DIGIT = new DecodeException( + "isHexDigit"); + + /** %-encoded slash is forbidden in resource path */ + private static final IOException EXCEPTION_SLASH = new DecodeException( + "noSlash"); + public UDecoder() { } @@ -57,18 +81,20 @@ public final class UDecoder { int idx= ByteChunk.indexOf( buff, start, end, '%' ); int idx2=-1; - if( query ) - idx2= ByteChunk.indexOf( buff, start, end, '+' ); + if( query ) { + idx2= ByteChunk.indexOf( buff, start, (idx >= 0 ? idx : end), '+' ); + } if( idx<0 && idx2<0 ) { return; } - // idx will be the smallest positive inxes ( first % or + ) - if( idx2 >= 0 && idx2 < idx ) idx=idx2; - if( idx < 0 ) idx=idx2; + // idx will be the smallest positive index ( first % or + ) + if( (idx2 >= 0 && idx2 < idx) || idx < 0 ) { + idx=idx2; + } + + boolean noSlash = !(ALLOW_ENCODED_SLASH || query); - boolean noSlash = !(ALLOW_ENCODED_SLASH || query); - for( int j=idx; j<end; j++, idx++ ) { if( buff[ j ] == '+' && query) { buff[idx]= (byte)' ' ; @@ -77,18 +103,18 @@ public final class UDecoder { } else { // read next 2 digits if( j+2 >= end ) { - throw new CharConversionException("EOF"); + throw EXCEPTION_EOF; } byte b1= buff[j+1]; byte b2=buff[j+2]; if( !isHexDigit( b1 ) || ! isHexDigit(b2 )) - throw new CharConversionException( "isHexDigit"); + throw EXCEPTION_NOT_HEX_DIGIT; j+=2; int res=x2c( b1, b2 ); - if (noSlash && (res == '/')) { - throw new CharConversionException( "noSlash"); - } + if (noSlash && (res == '/')) { + throw EXCEPTION_SLASH; + } buff[idx]=(byte)res; } } @@ -122,14 +148,17 @@ public final class UDecoder { int idx= CharChunk.indexOf( buff, start, cend, '%' ); int idx2=-1; - if( query ) - idx2= CharChunk.indexOf( buff, start, cend, '+' ); + if( query ) { + idx2= CharChunk.indexOf( buff, start, (idx >= 0 ? idx : cend), '+' ); + } if( idx<0 && idx2<0 ) { return; } - - if( idx2 >= 0 && idx2 < idx ) idx=idx2; - if( idx < 0 ) idx=idx2; + + // idx will be the smallest positive index ( first % or + ) + if( (idx2 >= 0 && idx2 < idx) || idx < 0 ) { + idx=idx2; + } for( int j=idx; j<cend; j++, idx++ ) { if( buff[ j ] == '+' && query ) { @@ -140,12 +169,12 @@ public final class UDecoder { // read next 2 digits if( j+2 >= cend ) { // invalid - throw new CharConversionException("EOF"); + throw EXCEPTION_EOF; } char b1= buff[j+1]; char b2=buff[j+2]; if( !isHexDigit( b1 ) || ! isHexDigit(b2 )) - throw new CharConversionException("isHexDigit"); + throw EXCEPTION_NOT_HEX_DIGIT; j+=2; int res=x2c( b1, b2 ); Modified: tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml?rev=1301123&r1=1301122&r2=1301123&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc6.0.x/trunk/webapps/docs/changelog.xml Thu Mar 15 18:14:44 2012 @@ -103,6 +103,9 @@ parameters, as documentation says, instead of <code>(maxParameterCount-1)</code>. (kkolinko) </fix> + <fix> + Slightly improve performance of UDecoder.convert(). (kkolinko) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org