Thanks for the comments Kin-Man. Given those comments and a look at the jasper2 
code I have come up with the patch below. After profiling jasper2 I saw that 
there was indeed a speed improvement over Jasper. However the excessive creation 
of File objects and getting files from URL's was still a problem.
        I did as you suggested and used the JspServletWrapper object to hold all of 
the 
required data. As well I set up this version to fall back to reading JSP's from 
a URL if reading the File object doesn't work.
        I found in my testing that the jasper engine used ~15% of the request time in 
loadJSP, jasper2 used ~12%, and my change uses ~1%. The only thing my code does 
not do is force a reload of the .class file if it is deleted. My code only 
causes a recompile if the jsp changes. I can look into modifying it to handle 
this situation as well if required. I look forward to your feedback.

Kin-Man Chung wrote:

> Duncan, I looked at your patch carefully, looks like Remy's work on
> jasper2 already addressed the issues that you are trying to solved.
> In fact, Remy only creates a compiler for the container, whereas you
> would have created a compiler for each jsp page.  OTOH, you save the
> modification date for each page in a hashtable, so is potentially
> faster when checking whether a jsp needs to be send to the compiler.
> I may incoporate your idea on this one later, maybe reusing the
> JspServletWrapper class instead of using another hashtabl, since that
> **IS** a per page object.
> 
> Thanks again for the patch.  If you wish, you should try running with
> japser2, and compare its performance with the one you patched.
> 
> 
> 


--- JspServlet.java.orig        Mon Apr 29 20:50:33 2002
+++ JspServlet.java     Mon Apr 29 17:34:28 2002
@@ -129,6 +129,11 @@
          JspCompilationContext ctxt = null;
          String outDir = null;
          long available = 0L;
+
+ 
        File    jspFile                 = null;
+        long   nLastModified   = 0;
+        boolean bCompiling             = false;
+ 
        boolean bInWar                  = false;
        
        JspServletWrapper(String jspUri, boolean isErrorPage) {
            this.jspUri = jspUri;
@@ -276,6 +281,103 @@
            if (theServlet != null)
                theServlet.destroy();
        }
+
+ 
     /**
+ 
      * This function takes the relative name of a jsp file and tries
+ 
      * to determine whether it has changed since the last time this
+ 
      * was called.
+ 
      */
+ 
     private boolean hasJspChanged() {
+ 
        try     {
+ 
                //get the last time the file was modified and the
+ 
                //last time it was modified that we compiled
+ 
                long             
                nMod = getModifiedTime();
+ 
                        
+ 
                //if we have not compiled before, or the file has changed.
+ 
                if (nMod == 0 || (nLastModified != nMod && !isCompiling(nMod))) {
+ 
                        return true;
+ 
                }
+ 
                        
+ 
                        waitForCompile();
+
+ 
                return false;
+ 
        } catch(IOException ioEx) {
+ 
                //ignore so that the normal logic will kick in.
+ 
        }
+ 
        
+ 
        return true;
+ 
     }
+
+ 
     /**
+ 
      * Gets the time that a particular JSP file was last modified.
+ 
      */        
+ 
     private long getModifiedTime()
+ 
        throws IOException {
+ 
                if (bInWar)     {
+ 
                        return nLastModified;
+ 
                }
+ 
                
+ 
                if (jspFile == null)
+ 
                {
+ 
                        //if is FAR faster to create a file object and get its
+ 
                        //last modified time than to open a URL connection to
+ 
                        //the file and get the last modified time that way.
+ 
                        String  strPath = 
getServletConfig().getServletContext().getRealPath(jspUri);
+ 
                        jspFile = new File(strPath);
+ 
                }
+ 
                
+ 
                try     {
+ 
                        //this will return 0 if the file does not exist.
+ 
                long nRet = jspFile.lastModified();
+ 
                        
+ 
                        if (nRet != 0){
+ 
                                return nRet;
+ 
                        }
+ 
                } catch(Exception ex)   {
+ 
                        //ignore and fall back.
+ 
                }
+ 
                
+ 
                try {
+ 
                    URL jspUrl = ctxt.getResource(jspUri);
+ 
                    if (jspUrl != null)
+ 
                        {
+ 
                                bInWar = true;
+ 
                            return jspUrl.openConnection().getLastModified();
+ 
                        }
+ 
                } catch (Exception e) {
+ 
                        //ignore
+ 
                }
+
+ 
                return 0;
+ 
     }
+
+ 
     /**
+ 
      * This function determines if the jsp this represents is
+ 
      * already being compiled. If it is not then the new modification
+ 
      * time is saved, and false is returned meaning the caller is
+ 
      * allowed to compile the JSP.
+ 
      */
+ 
     synchronized boolean isCompiling(long nNewModTime) {
+ 
        if (bCompiling) {
+ 
                return true;
+ 
        }
+
+ 
        nLastModified = nNewModTime;
+ 
        bCompiling = true;
+
+ 
        return false;
+ 
     }
+ 
        
+ 
        void doneCompile()
+ 
        {
+ 
                bCompiling = false;
+ 
        }
+ 
        
+ 
        void waitForCompile()
+ 
        {
+ 
                while (bCompiling)
+ 
                        Thread.yield();
+ 
        }
      }
        
        
@@ -594,57 +696,68 @@
                   jsw.outDir, isErrorPage, options,
                   req, res);
          }
-        JspCompilationContext ctxt = jsw.ctxt;
- 
boolean outDated;
-        Compiler compiler = ctxt.createCompiler();
-
-        try {
- 
     synchronized(jsw) {
- 
        // Synchronizing on jsw enables simultaneous compilations of
- 
        // different pages, but not the same page.
- 
        outDated = compiler.isOutDated();
- 
        if (outDated)
- 
            compiler.compile();
-            }
-        } catch (FileNotFoundException ex) {
-            compiler.removeGeneratedFiles();
-            throw ex;
-        } catch (JasperException ex) {
-            throw ex;
-        } catch (Exception ex) {
- 
     throw new JasperException(Constants.getString("jsp.error.unable.compile"),
-                                      ex);
- 
}
+ 
        
+        //this short circuits the need to create a copiler and do a test compile.
+        if (!jsw.hasJspChanged())      {
+ 
                return false;
+        }
+ 
        
+ 
        try{
+ 
         JspCompilationContext ctxt = jsw.ctxt;
+ 
                boolean outDated;
+ 
         Compiler compiler = ctxt.createCompiler();
+ 

+ 
         try {
+ 
            synchronized(jsw) {
+ 
                // Synchronizing on jsw enables simultaneous compilations of
+ 
                // different pages, but not the same page.
+ 
                outDated = compiler.compile();
+ 
             }
+ 
         } catch (FileNotFoundException ex) {
+ 
             compiler.removeGeneratedFiles();
+ 
             throw ex;
+ 
         } catch (JasperException ex) {
+ 
             throw ex;
+ 
         } catch (Exception ex) {
+ 
            throw new JasperException(Constants.getString("jsp.error.unable.compile"),
+ 
                                       ex);
+ 
        }

-        // Reload only if it's outdated
- 
if ((jsw.servletClass == null) || outDated) {
- 
     try {
- 
        synchronized (jsw) {
- 
            if (jsw.servletClass == null || outDated) {
- 
                URL [] urls = new URL[1];
- 
                File outputDir = new File(normalize(ctxt.getOutputDir()));
- 
                urls[0] = outputDir.toURL();
- 
                jsw.loader = new JasperLoader(
- 
                                        urls,ctxt.getServletClassName(),
- 
                                        parentClassLoader,
- 
                                        permissionCollection,
- 
                                        codeSource);
- 
                jsw.servletClass = jsw.loader.loadClass(
- 
                        Constants.JSP_PACKAGE_NAME + "." +
- 
                        ctxt.getServletClassName());
+ 
         // Reload only if it's outdated
+ 
        if ((jsw.servletClass == null) || outDated) {
+ 
            try {
+ 
                synchronized (jsw) {
+ 
                    if (jsw.servletClass == null || outDated) {
+ 
                        URL [] urls = new URL[1];
+ 
                        File outputDir = new File(normalize(ctxt.getOutputDir()));
+ 
                        urls[0] = outputDir.toURL();
+ 
                        
+ 
                        jsw.loader = new JasperLoader(
+ 
                                                urls,ctxt.getServletClassName(),
+ 
                                                parentClassLoader,
+ 
                                                permissionCollection,
+ 
                                                codeSource);
+ 
                        jsw.servletClass = jsw.loader.loadClass(
+ 
                                Constants.JSP_PACKAGE_NAME + "." +
+ 
                                ctxt.getServletClassName());
+ 
                    }
+ 
                }
+ 
            } catch (ClassNotFoundException cex) {
+ 
                        System.out.println("Caught: " + cex);
+ 
                throw new JasperException(
+ 
                    Constants.getString("jsp.error.unable.load"),cex);
+ 
            } catch (MalformedURLException mue) {
+ 
                 System.out.println("Caught: " + mue);
+ 
                 throw new JasperException(
+ 
                    Constants.getString("jsp.error.unable.load"),mue);
                    }
+ 
        
+ 
        }
+ 
        
+ 
        return outDated;
+ 
        } finally {
+ 
                jsw.doneCompile();
                }
- 
     } catch (ClassNotFoundException cex) {
- 
        throw new JasperException(
- 
            Constants.getString("jsp.error.unable.load"),cex);
- 
     } catch (MalformedURLException mue) {
-                throw new JasperException(
- 
            Constants.getString("jsp.error.unable.load"),mue);
- 
     }
- 

- 
}
- 

- 
return outDated;
      }


-- 
Duncan McLean
Hummingbird Ltd.
613-548-4355 x1539
http://www.hummingbird.com


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to