Bug 57583 - Performance issue evaluating EL in custom tags (tagx) due to inefficient calls to java.lang.Class.forName()
Summary: Performance issue evaluating EL in custom tags (tagx) due to inefficient call...
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Jasper (show other bugs)
Version: 8.0.32
Hardware: Sun Solaris
: P2 normal (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
: 59699 (view as bug list)
Depends on:
Blocks:
 
Reported: 2015-02-13 17:43 UTC by Yevgeny V
Modified: 2016-06-14 08:24 UTC (History)
2 users (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Yevgeny V 2015-02-13 17:43:33 UTC
Method getValue of ScopedAttributeELResolver in some cases calls ImportHandler.resolveClass(..) that ends up looking the class by name.
It seems that the look-up is made whenever a custom tag attribute that is not  initialized yet (==null) is used in EL. I have plenty of these cases in custom tags, they are optional tag parameters, and this makes JSP rendering really slow.

At the moment I've replaced lib/jsp-api.jar with Glassfish implementation and it seems to do the trick. I hope the rendering result itself is not affected by this substitution (I would be very thankful if someone could tell me what the possible drawbacks might be, or provide arguments on why it is not a good idea to replace jsp-api implementation).
Comment 1 Mark Thomas 2015-02-16 14:50:49 UTC
In theory, you should be safe swapping API implementation classes but it is likely you will see different behaviour as different implmentations will have fixed different bugs. Personally, I wouldn't swap implementations. I'd rather stick with a known problem than risk an untested, unsupported combination.

From a Tomcat PoV we are normally only going to support folks that are using the Tomcat API implementations.

In this case the reason you see better performance is that Glassfish hasn't added the required support for imports in the version you are using. Looking at the Glassfish source it appears that this is partially fixed (statics don't appear to be supported yet) in trunk which should be in the next release.

In terms of solving the performance problem I think we need to cache "Not Found" results as well. I'll take a look.
Comment 2 Mark Thomas 2015-02-16 15:06:23 UTC
Fixed in trunk and 8.0.x for 8.0.21 onwards.
Comment 3 Arne Bultman 2015-09-09 08:59:43 UTC
Maybe I'm missing something, but even with this cache we still have this problem. Since a en ELContextImpl seems to be created with every jsp render, the cache has very limited effect, we're still seeing dramatically slower rendertimes with this implementation. Am I missing something?
Comment 4 Mark Thomas 2015-09-09 09:59:07 UTC
What you are missing is that with this change in the EL spec resolving of unscoped attributes got a lot slower. We have fixed it as best we can and I am not aware of any further improvements that could be made while staying spec complaint. Suggestions for improvements are welcome but they do need to maintain spec compliance.

The work-around is to add the appropriate scope to your attributes so use ${requestScope.foo}, ${applicationScope.foo} etc. rather than ${foo}.
Comment 5 Arne Bultman 2015-09-09 12:08:54 UTC
Isn't that lookup relatively static, as in could the caching of lookups not be shared across instances of ImportHandler rather than having a cache per instance?

I need to read up on the spec more.

Thanks for your help, so far. Will look into adding the scopes.
Comment 6 Mark Thomas 2016-03-10 12:13:08 UTC
I think I have a way to address the performance issues without breaking the spec.
Comment 7 Mark Thomas 2016-03-10 14:29:39 UTC
I've implemented an improvement for 9.0.x (9.0.0.M4 onwards) and 8.0.x (8.0.33 onwards).

The improvement only works when Tomcat's JSP API implementation is used in conjunction with Tomcat's EL implementation.

In my local testing the time for a single request with a single attribute lookup was reduced from ~1ms to ~0.1ms.
Comment 8 Konstantin Kolinko 2016-03-11 16:31:11 UTC
For reference: recent threads:
"Intermittent ClassNotFoundException in Jasper EL evaluation"
http://tomcat.markmail.org/thread/4a4x4ms63hrkpoix

"r1734418"
http://tomcat.markmail.org/thread/fdacbeusrgvlqd2w
Comment 9 Henning Brune 2016-03-24 09:11:03 UTC
(In reply to Mark Thomas from comment #7)
> I've implemented an improvement for 9.0.x (9.0.0.M4 onwards) and 8.0.x
> (8.0.33 onwards).
> 
> The improvement only works when Tomcat's JSP API implementation is used in
> conjunction with Tomcat's EL implementation.
> 
> In my local testing the time for a single request with a single attribute
> lookup was reduced from ~1ms to ~0.1ms.

Any improvement would be highly welcome. After our migration from Tomcat 7 to 8.0.32 many pages in our applications became more or less unusable. We make heavy use of EL and custom tags and would have to rebuild large parts of our applications, if the performance would stay on the current level.

Is there any information about the release date for 8.0.33?
Comment 10 Henning Brune 2016-03-25 12:01:09 UTC
I just verified the improvements made in v8.0.33 in our application: Running on a current build the execution time on the relevant JSP parts is reduced to 1/10th.
Comment 11 Mark Thomas 2016-06-14 08:24:29 UTC
*** Bug 59699 has been marked as a duplicate of this bug. ***