https://bz.apache.org/bugzilla/show_bug.cgi?id=65124

            Bug ID: 65124
           Summary: Inefficient generated JSP code
           Product: Tomcat 10
           Version: unspecified
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Jasper
          Assignee: dev@tomcat.apache.org
          Reporter: jeng...@amazon.com
  Target Milestone: ------

Created attachment 37726
  --> https://bz.apache.org/bugzilla/attachment.cgi?id=37726&action=edit
Code references - examples and partial solution

Multiple of our large, publicly-facing applications contains thousands of JSPs.
 Some are executed more than others but all of the classes are loaded into
memory for the lifetime of the application.  This has stressed the JVM in
various ways and we identified several ways to improve the generated classes
(listed below).  Note that I am describing the output of the JSP compilation,
and not the compilation itself.

The impact of our in-house fix (Tomcat8) depended on the application but in
general we saw:

Output .class files decreased in size by 20 - 40%
JVM metaspace decreased by 20 - 90MB
Code cache size decreased by 5-10%
Small latency decrease (single-digit milliseconds)
Small cpu decrease (present but difficult to quantify)


Here are the issues we'd like to see addressesd:
1. Near-duplicate methods: each call to <c:set> generated its own method, even
when a single property varied.  For example
<c:set var="test" value="${test1}"/>
<c:set var='test" value="${test2}"/>

generates two distinct methods (such as "_jspx_meth_c_005fset_005f2") even
though they vary only by a constant string.  Generating a single method (such
as
"_callTag_org_apache_taglibs_standard_tag_rt_core_SetTag_With_var_And_value") 
and parameterizing the value property eliminates one method for each matching
instance within the JSP.

2. Tag pooling is disabled in all of our applications, and that value does not
change at runtime - however tag pooling logic is executed anyway.  This is
generally trivial logic but it is executed many, many times... and it is
generated many, many times.  This is wasteful at execution time and also makes
the methods larger than necessary.

3. There is wasteful method overhead such as aliasing parameters
(_jspx_page_context -> pageContext) and an unused call to
_jspx_page_context.getOut().  The JIT compiler will clean up much of that at
runtime, however this is still present in the class file and therefore adds
load to various native spaces, creates extra work during warmup (before JIT
kicks in), and makes the JIT operations a bit slower.

These optimizations are not significantly impactful to a single JSP, however
they do add up in large applications, as described above.

The attached file contains several methods:
1. _jspx_meth_c_005fset_005f2() - a generated method from a typical <c:set>
2. _jspx_meth_c_005fset_005f3() - a generated method from a <c:set> with a
body.  This illustrates the significant differences when a tag contains a body;
our fix avoided this by leaving body tags as-is and only modifying empty tags.
3. _callTag_org_apache_taglibs_standard_tag_rt_core_SetTag_With_var_And_value()
- a generated method from our fixed code that generically handles all <c:set
value="" var=""/> tags.  This method is reproduced in all of our JSPs with one
or more occurrences of that tag (with no body!) and is referenced as many as
150 times.  Note that the line count is reduced from 21 to 8.
4. generateOptimizedTagCall() - this is from our internal fix and is
responsible for generating the reusable methods, such as the immediately
previous example.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to