title: jsp:include , performance, modularization, alternatives and best practices, Part 96
body: <p>This is a follow-up to the 'overhead of jsp include' question below:</p>
  
  <p><a href="https://stackoverflow.com/questions/1479218/jsp-performance-using-jspinclude">JSP Performance using jsp:include</a></p>
  
  <p>In our application, developers have 'modularized' jsp fragments by heavy use of "jsp:includes" for "common" jsp code repeated throughout the application.</p>
  
  <p><strong>Pros</strong></p>
  
  <p>The pro's are as follows:</p>
  
  <ul>
  <li><p>it's DRY-- we define the jsp fragment once. This is a big help when you need to change some html and don't need to find/replace/search/destroy.</p></li>
  <li><p>it's fairly easy to follow: you clearly pass in the parameters. When you edit the 'included' page, you 'know what you're getting', i.e. vs. some 'global variables' declared in the 'including/calling' page.</p></li>
  </ul>
  
  <p><strong>Cons</strong></p>
  
  <ul>
  <li>performance overhead of the additional request</li>
  </ul>
  
  <p><strong>Questions</strong></p>
  
  <p>So as a follow-on: </p>
  
  <ul>
  <li>how much performance overhead does a 'jsp:include' incur? It's not obvious from the tomcat code (though you see it does a whole lot more than would an inline call). Also in profiling the app I've never  requestDispatcher.include() or invoke() methods appears as hotspots.</li>
  <li>could someone point as to where precisely lies the bulk of the overhead? (i.e. method X in class Y) Or whether it's just all the "little stuff" (e.g. setting attributes or object creation and subsequent GC) that happens with each request?</li>
  <li>what are the alternatives? (AFAIK @include and jsp:include. anything else?)</li>
  <li>(Stupid bonus question) why couldn't the servlet engine 'include' the jsp at compile time, i.e like an 'inline macro with parameters' so that we developers could get the clarity of 'jsp:include' and the peformance  of '@include'. </li>
  </ul>
  
  <p>I've wondered about this last question for a while. I've used code generation tools in a past life and never quite understood the lack of options for including jsp fragments.</p>
  
  <p>For the benefit of the reader I've included the tomcat 'applicationDispatcher.invoke()' method (tomcat 5.5. sorry if it's dated). For clarity, I've pruned the exception handling.</p>
  
  <p>thanks in advance</p>
  
  <p>will</p>
  
  <pre><code>    private void invoke(ServletRequest request, ServletResponse response,
          State state) throws IOException, ServletException {
  
      // Checking to see if the context classloader is the current context
      // classloader. If it's not, we're saving it, and setting the context
      // classloader to the Context classloader
      ClassLoader oldCCL = Thread.currentThread().getContextClassLoader();
      ClassLoader contextClassLoader = context.getLoader().getClassLoader();
  
      if (oldCCL != contextClassLoader) {
          Thread.currentThread().setContextClassLoader(contextClassLoader);
      } else {
          oldCCL = null;
      }
  
      // Initialize local variables we may need
      HttpServletResponse hresponse = (HttpServletResponse) response;
      Servlet servlet = null;
      IOException ioException = null;
      ServletException servletException = null;
      RuntimeException runtimeException = null;
      boolean unavailable = false;
  
      // Check for the servlet being marked unavailable
      if (wrapper.isUnavailable()) {
          wrapper.getLogger().warn(
                  sm.getString("applicationDispatcher.isUnavailable", 
                  wrapper.getName()));
          long available = wrapper.getAvailable();
          if ((available &gt; 0L) &amp;&amp; (available &lt; Long.MAX_VALUE))
              hresponse.setDateHeader("Retry-After", available);
          hresponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm
                  .getString("applicationDispatcher.isUnavailable", wrapper
                          .getName()));
          unavailable = true;
      }
  
      // Allocate a servlet instance to process this request
      try {
          if (!unavailable) {
              servlet = wrapper.allocate();
          }
      }
     ...exception handling here....
  
      // Get the FilterChain Here
      ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
      ApplicationFilterChain filterChain = factory.createFilterChain(request,
                                                              wrapper,servlet);
      // Call the service() method for the allocated servlet instance
      try {
          String jspFile = wrapper.getJspFile();
          if (jspFile != null)
              request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
          else
              request.removeAttribute(Globals.JSP_FILE_ATTR);
          support.fireInstanceEvent(InstanceEvent.BEFORE_DISPATCH_EVENT,
                                    servlet, request, response);
          // for includes/forwards
          if ((servlet != null) &amp;&amp; (filterChain != null)) {
             filterChain.doFilter(request, response);
           }
          // Servlet Service Method is called by the FilterChain
          request.removeAttribute(Globals.JSP_FILE_ATTR);
          support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
                                    servlet, request, response);
      }
     ...exception handling here....
  
      // Release the filter chain (if any) for this request
      try {
          if (filterChain != null)
              filterChain.release();
      }
     ...exception handling here....        
  
      // Deallocate the allocated servlet instance
      try {
          if (servlet != null) {
              wrapper.deallocate(servlet);
          }
      }
     ...exception handling here....
  
      // Reset the old context class loader
      if (oldCCL != null)
          Thread.currentThread().setContextClassLoader(oldCCL);
  
      // Unwrap request/response if needed
      // See Bugzilla 30949
      unwrapRequest(state);
      unwrapResponse(state);
  
      // Rethrow an exception if one was thrown by the invoked servlet
      if (ioException != null)
          throw ioException;
      if (servletException != null)
          throw servletException;
      if (runtimeException != null)
          throw runtimeException;
  
  }
  </code></pre>