2016-03-10 17:22 GMT+03:00 <[email protected]>:
> Author: markt
> Date: Thu Mar 10 14:22:51 2016
> New Revision: 1734418
>
> URL: http://svn.apache.org/viewvc?rev=1734418&view=rev
> Log:
> Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=57583
> Improve long standing performance issue with EL and undefined attributes.
>
> Modified:
> tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java
> tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java
> tomcat/trunk/webapps/docs/changelog.xml
>
> Modified:
> tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java
> URL:
> http://svn.apache.org/viewvc/tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java?rev=1734418&r1=1734417&r2=1734418&view=diff
> ==============================================================================
> --- tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java
> (original)
> +++ tomcat/trunk/java/javax/servlet/jsp/el/ScopedAttributeELResolver.java Thu
> Mar 10 14:22:51 2016
> @@ -35,6 +35,20 @@ import javax.servlet.jsp.PageContext;
> */
> public class ScopedAttributeELResolver extends ELResolver {
>
> + // Indicates if a performance short-cut is available
> + private static final Class<?> AST_IDENTIFIER_KEY;
> +
> + static {
> + Class<?> key = null;
> + try {
> + key = Class.forName("org.apache.el.parser.AstIdentifier");
> + } catch (Exception e) {
> + // Ignore: Expected if not running on Tomcat. Not a problem since
> + // this just allows a short-cut.
> + }
> + AST_IDENTIFIER_KEY = key;
> + }
> +
> @Override
> public Object getValue(ELContext context, Object base, Object property) {
> if (context == null) {
> @@ -51,10 +65,26 @@ public class ScopedAttributeELResolver e
> result = page.findAttribute(key);
>
> if (result == null) {
> + boolean resolveClass = true;
> + // Performance short-cut available when running on Tomcat
> + if (AST_IDENTIFIER_KEY != null) {
> + // Tomcat will set this key to Boolean.TRUE if the
> + // identifier is a stand-alone identifier (i.e.
> + // identifier) rather than part of an AstValue (i.e.
> + // identifier.something). Imports do not need to be
> + // checked if this is a stand-alone identifier
> + Boolean value = (Boolean)
> context.getContext(AST_IDENTIFIER_KEY);
> + if (value != null && value.booleanValue()) {
> + resolveClass = false;
> + }
> + }
> // This might be the name of an imported class
> ImportHandler importHandler = context.getImportHandler();
> if (importHandler != null) {
> - Class<?> clazz = importHandler.resolveClass(key);
> + Class<?> clazz = null;
> + if (resolveClass) {
> + clazz = importHandler.resolveClass(key);
> + }
> if (clazz != null) {
> result = new ELClass(clazz);
> }
>
> Modified: tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java
> URL:
> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java?rev=1734418&r1=1734417&r2=1734418&view=diff
> ==============================================================================
> --- tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java (original)
> +++ tomcat/trunk/java/org/apache/el/parser/AstIdentifier.java Thu Mar 10
> 14:22:51 2016
> @@ -77,7 +77,27 @@ public final class AstIdentifier extends
>
> // EL Resolvers
> ctx.setPropertyResolved(false);
> - Object result = ctx.getELResolver().getValue(ctx, null, this.image);
> + Object result;
> + /* Putting the Boolean into the ELContext is part of a performance
> + * optimisation for ScopedAttributeELResolver. When looking up "foo",
> + * the resolver can't differentiate between ${ foo } and ${ foo.bar
> }.
> + * This is important because the expensive class lookup only needs to
> + * be performed in the later case. This flag tells the resolver if
> the
> + * lookup can be skipped.
> + */
> + if (parent instanceof AstValue) {
> + ctx.putContext(this.getClass(), Boolean.FALSE);
> + } else {
> + ctx.putContext(this.getClass(), Boolean.TRUE);
> + }
Honestly, I do not understand the above if/else block.
I do not see how the difference of "${ foo } vs ${ foo.bar }" maps
into "(parent instanceof AstValue)" check.
What is the meaning of "parent" in Ast?
What possible values can it have?
Does this handle method calls, such as ${System.currentTimeMillis()} ?
> + try {
> + result = ctx.getELResolver().getValue(ctx, null, this.image);
> + } finally {
> + // Always reset the flag to false so the optimisation is not
> applied
> + // inappropriately
> + ctx.putContext(this.getClass(), Boolean.FALSE);
> + }
> +
> if (ctx.isPropertyResolved()) {
> return result;
> }
Below these lines the AstIdentifier does its own
ImportHandler.resolveClass(), resolveStatic() calls.
This duplicates the work performed by ScopedAttributeELResolver and I
wonder whether it is necessary.
Those lines originate from
http://svn.apache.org/viewvc?diff_format=l&view=revision&revision=1504286
> Modified: tomcat/trunk/webapps/docs/changelog.xml
> URL:
> http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1734418&r1=1734417&r2=1734418&view=diff
> ==============================================================================
> --- tomcat/trunk/webapps/docs/changelog.xml (original)
> +++ tomcat/trunk/webapps/docs/changelog.xml Thu Mar 10 14:22:51 2016
> @@ -222,6 +222,12 @@
> <update>
> Update to the Eclipse JDT Compiler 4.5.1. (markt)
> </update>
> + <fix>
> + <bug>57583</bug>: Improve the performance of
> + <code>javax.servlet.jsp.el.ScopedAttributeELResolver</code> when
> + resolving attributes that do not exist. This improvement only works
> when
> + Jasper is used with with Tomcat's EL implementation. (markt)
> + </fix>
> </changelog>
> </subsection>
> <subsection name="WebSocket">
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]