Re: [PATCH] possible speed enhancement to JspServlet.java

2002-04-30 Thread Duncan McLean

The numbers I got were for a fairly specific application. The page request I was 
making did includes of 10 jsp's in total (which would account for the difference 
in my results and yours I think).
I really like the idea of having a server vs development setting. I'll take a 
look at that this morning. Might it be a good idea to have a manual way to force 
a JSP reload in a production environment? I see reading your comment that you 
can reload the JSP by reloading the web application, but I'm not sure the 
container I'm using has that option available in a straight forward manner. 
Something simple like a parameter in the URL like jasper_jsp_reload=true would 
make it relatively easy to modify a production system without taking it off-line 
  even briefly.

Remy Maucherat wrote:

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.

 
 A much simpler solution would be to allow disabling reloading altogether for
 production systems. I've committed a patch which does that.
 
 That way, loadJSP can use 0% and everything stays very simple.
 
 What do you think ?
 
 Remy
 
 
 --
 To unsubscribe, e-mail:   mailto:[EMAIL PROTECTED]
 For additional commands, e-mail: mailto:[EMAIL PROTECTED]
 
 


-- 
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]




Re: [PATCH] possible speed enhancement to JspServlet.java

2002-04-30 Thread Remy Maucherat

 The numbers I got were for a fairly specific application. The page request
I was
 making did includes of 10 jsp's in total (which would account for the
difference
 in my results and yours I think).
 I really like the idea of having a server vs development setting. I'll
take a
 look at that this morning. Might it be a good idea to have a manual way to
force
 a JSP reload in a production environment? I see reading your comment that
you
 can reload the JSP by reloading the web application, but I'm not sure the
 container I'm using has that option available in a straight forward
manner.
 Something simple like a parameter in the URL like jasper_jsp_reload=true
would
 make it relatively easy to modify a production system without taking it
off-line
   even briefly.

That kind of setting could be used for a DOS attack (making the server
recompile pages all the time). It should rather be something like
check_modified=true. Actually, I'll have to check what the precompile
attribte does. It may already be doing that; otherwise, I'll probably add
the other.

Remy


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




Re: [PATCH] possible speed enhancement to JspServlet.java

2002-04-29 Thread Duncan McLean

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.origMon 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;
+
+ 
FilejspFile = 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;

Re: [PATCH] possible speed enhancement to JspServlet.java

2002-04-29 Thread Remy Maucherat

 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.

I don't agree with those numbers. Accoding to my testing it is far less
significant. I got some very significant increase in the throughtput numbers
to confirm that (using index.jsp).

Remy


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




Re: [PATCH] possible speed enhancement to JspServlet.java

2002-04-29 Thread Remy Maucherat

 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.

A much simpler solution would be to allow disabling reloading altogether for
production systems. I've committed a patch which does that.

That way, loadJSP can use 0% and everything stays very simple.

What do you think ?

Remy


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




Re: [PATCH] possible speed enhancement to JspServlet.java

2002-04-22 Thread Kin-Man Chung

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.


 Date: Fri, 19 Apr 2002 16:58:54 -0700 (PDT)
 From: Kin-Man Chung [EMAIL PROTECTED]
 Subject: Re: [PATCH] possible speed enhancement to JspServlet.java
 To: [EMAIL PROTECTED]
 MIME-version: 1.0
 Content-transfer-encoding: 7BIT
 Content-MD5: Pd6UqZXWO7AIRUPw9V+AAQ==
 Delivered-to: mailing list [EMAIL PROTECTED]
 Mailing-List: contact [EMAIL PROTECTED]; run by ezmlm
 X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N
 List-Post: mailto:[EMAIL PROTECTED]
 List-Subscribe: mailto:[EMAIL PROTECTED]
 List-Unsubscribe: mailto:[EMAIL PROTECTED]
 List-Help: mailto:[EMAIL PROTECTED]
 List-Id: Tomcat Developers List tomcat-dev.jakarta.apache.org
 
 Thank you for the patch!  It looks interesting!  I'll definitely look
 at it carefully and apply it to jasper or jasper2 when I have time,
 most probably sometime next week.
 
  Date: Fri, 19 Apr 2002 17:09:49 -0400
  From: Duncan McLean [EMAIL PROTECTED]
  Subject: [PATCH] possible speed enhancement to JspServlet.java
  To: Tomcat Developers List [EMAIL PROTECTED]
  MIME-version: 1.0
  Content-transfer-encoding: 7bit
  X-Accept-Language: en,pdf
  Delivered-to: mailing list [EMAIL PROTECTED]
  Mailing-List: contact [EMAIL PROTECTED]; run by ezmlm
  User-Agent: Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:0.9.4.1) 
 Gecko/20020314 Netscape6/6.2.2
  X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N
  List-Post: mailto:[EMAIL PROTECTED]
  List-Subscribe: mailto:[EMAIL PROTECTED]
  List-Unsubscribe: mailto:[EMAIL PROTECTED]
  List-Help: mailto:[EMAIL PROTECTED]
  List-Id: Tomcat Developers List tomcat-dev.jakarta.apache.org
  
  I'm new to this list (and the jasper code), so please let me know if 
 I've
  submitted this incorrectly.
  I was doing some profiling of the server side environment that I work on
  and noticed that quite a bit of time was being used in the JSP engine. After
  further investigation I noticed that each JSP request that comes into the 
 jasper
  engine generates a new compiler object and attempt at compilation. As much 
as 
 15%
  of the time of a JSP request is wasted this way.
  The change I made attempts to read the last modified date from the JSP
  file being request. A comparison is made against known last modified time
  for the current compiled version, if they are different then the code flows
  as it used to. If the times are the same then the rest of loadJSP is 
skipped.
  In my test application which relies on calling ~10 jsp files to generate
  a single page I found a speed improvement of ~25-50ms (on a PIII 650).
  There may be better ways to do this. I concentrated my fix here because
  it is where the profiler said the problem was. One drawback of the code I'm
  submitting is that if there are a large number of JSP's the Hashtable I use 
to
  store information may get large. However I can't see that being a problem 
 until
  a site has 10,000 jsp's.
  The change I'm submitting may not be the correct way to approach the
  problem. Either way I think this is an issue that deserves some attention so
  if someone can suggest a better fix please do.
 
 
 --
 To unsubscribe, e-mail:   mailto:[EMAIL PROTECTED]
 For additional commands, e-mail: mailto:[EMAIL PROTECTED]
 


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




Re: [PATCH] possible speed enhancement to JspServlet.java

2002-04-20 Thread Remy Maucherat

 I'm new to this list (and the jasper code), so please let me know if I've
 submitted this incorrectly.
 I was doing some profiling of the server side environment that I work on
 and noticed that quite a bit of time was being used in the JSP engine.
After
 further investigation I noticed that each JSP request that comes into the
jasper
 engine generates a new compiler object and attempt at compilation. As much
as 15%
 of the time of a JSP request is wasted this way.
 The change I made attempts to read the last modified date from the JSP
 file being request. A comparison is made against known last modified time
 for the current compiled version, if they are different then the code
flows
 as it used to. If the times are the same then the rest of loadJSP is
skipped.
 In my test application which relies on calling ~10 jsp files to generate
 a single page I found a speed improvement of ~25-50ms (on a PIII 650).
 There may be better ways to do this. I concentrated my fix here because
 it is where the profiler said the problem was. One drawback of the code
I'm
 submitting is that if there are a large number of JSP's the Hashtable I
use to
 store information may get large. However I can't see that being a problem
until
 a site has 10,000 jsp's.
 The change I'm submitting may not be the correct way to approach the
 problem. Either way I think this is an issue that deserves some attention
so
 if someone can suggest a better fix please do.

I did a lot of opimizations in the Jasper 2
(jakarta-tomcat-connectors/jasper2) JspServlet. I don't know how much is
addressed by the patch that I already did. Could you check it out ?

Thanks,
Remy


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




[PATCH] possible speed enhancement to JspServlet.java

2002-04-19 Thread Duncan McLean

I'm new to this list (and the jasper code), so please let me know if I've
submitted this incorrectly.
I was doing some profiling of the server side environment that I work on
and noticed that quite a bit of time was being used in the JSP engine. After
further investigation I noticed that each JSP request that comes into the jasper
engine generates a new compiler object and attempt at compilation. As much as 15%
of the time of a JSP request is wasted this way.
The change I made attempts to read the last modified date from the JSP
file being request. A comparison is made against known last modified time
for the current compiled version, if they are different then the code flows
as it used to. If the times are the same then the rest of loadJSP is skipped.
In my test application which relies on calling ~10 jsp files to generate
a single page I found a speed improvement of ~25-50ms (on a PIII 650).
There may be better ways to do this. I concentrated my fix here because
it is where the profiler said the problem was. One drawback of the code I'm
submitting is that if there are a large number of JSP's the Hashtable I use to
store information may get large. However I can't see that being a problem until
a site has 10,000 jsp's.
The change I'm submitting may not be the correct way to approach the
problem. Either way I think this is an issue that deserves some attention so
if someone can suggest a better fix please do.

- * The JSP engine (a.k.a Jasper).
+ * The JSP engine (a.k.a Jasper)!
   *
   * The servlet container is responsible for providing a
   * URLClassLoader for the web application context Jasper
@@ -231,6 +232,32 @@
theServlet.destroy();
}
  }
+
+ 
/**
+ 
  * This class stores data on the last time a jsp was modified, and
+ 
  * whether it is currently being compiled.
+ 
  */
+ 
class JspModfificationData {
+ 
longnLastModified   = 0;
+ 
boolean bCompiling  = false;
+
+ 
/**
+ 
 * 
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;
+ 
}
+ 
}


  protected ServletContext context = null;
@@ -242,6 +269,7 @@
  protected String serverInfo;
  private PermissionCollection permissionCollection = null;
  private CodeSource codeSource = null;
+private Hashtable htModificationData = new Hashtable();

  static boolean firstTime = true;

@@ -473,6 +501,9 @@
  serviceJspFile(request, response, jspUri, null, precompile);
} catch (RuntimeException e) {
throw e;
+} catch (JasperError ex) {
+response.setContentType(text/html);
+response.getWriter().print(ex.getMessage());
} catch (ServletException e) {
throw e;
} catch (IOException e) {
@@ -509,86 +540,172 @@
  boolean loadJSP(String jspUri, String classpath,
boolean isErrorPage, HttpServletRequest req, HttpServletResponse res)
throws JasperException, FileNotFoundException
-{
- 
// First check if the requested JSP page exists, to avoid creating
- 
// unnecessary directories and files.
- 
if (context.getResourceAsStream(jspUri) == null)
- 
 throw new FileNotFoundException(jspUri);
-
- 
JspServletWrapper jsw=(JspServletWrapper) jsps.get(jspUri);
- 
if( jsw==null ) {
- 
 throw new JasperException(Can't happen - JspServletWrapper=null);
- 
}
-File outDir = null;
-try {
-URL outURL = options.getScratchDir().toURL();
-String outURI = outURL.toString();
-if( outURI.endsWith(/) )
-outURI = outURI + jspUri.substring(1,jspUri.lastIndexOf(/)+1);
-else
-outURI = outURI + jspUri.substring(0,jspUri.lastIndexOf(/)+1);;
-outURL = new URL(outURI);
-outDir = new File(outURL.getFile());
-if( !outDir.exists() ) {
-outDir.mkdirs();
-}
-} catch(Exception e) {
-throw new JasperException(No output directory:  + e.getMessage());
-}
- 
boolean firstTime = jsw.servletClass == null;
-JspCompilationContext ctxt = new JspEngineContext(parentClassLoader, 
classpath,
- context, jspUri, 
outDir.toString() + File.separator,
- isErrorPage, options,
- req, res);
- 
boolean outDated