tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Rainer Jung <rainer.j...@kippdata.de>
Subject Possible optimization for class loading?
Date Sun, 17 Nov 2019 15:40:04 GMT
I noticed a slowness during Webapp startup on the Winows platform. 
Investigation showed, that about three seconds of the webapp startup 
time - roughly 1/3 of the total time - was due to 
File.getCanonicalPath(). That call seems to be especially expensive on 
Windows, because it iterates over each component of the path in question 
and does at least three system calls on each of them. So if you app is 
installed in a somewhat deeply nested path, getCanonicalPath() gets 
especially expensive.

One can check this with a simple test app and running the ProcessMonitpr 
from SysInternals, which can nicely trace file system operations.

I noticed that by far the most occurrences happened during webapp class 
loading. StandardRoot initializes resources to contain a DirResourceSet 
first and then a JarResourceSet per WEB-INF/lib jar file.

Now any class loading (of not yet loaded classes) goes through the 
following stack (this is for TC 8.5):

...
java.base@13.0.1/java.io.File.getCanonicalPath(File.java:618)
org.apache.catalina.webresources.AbstractFileResourceSet.file(AbstractFileResourceSet.java:90)
org.apache.catalina.webresources.DirResourceSet.getResource(DirResourceSet.java:101)
org.apache.catalina.webresources.StandardRoot.getResourceInternal(StandardRoot.java:281)
org.apache.catalina.webresources.Cache.getResource(Cache.java:62)
org.apache.catalina.webresources.StandardRoot.getResource(StandardRoot.java:216)
org.apache.catalina.webresources.StandardRoot.getClassLoaderResource(StandardRoot.java:225)
org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2279)
org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:857)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1329)
- locked (a java.lang.Object@1797c4d) index 11 frame 
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1329)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1182)
...

In our case, the webapp does not have a WEB-INF/classes directory. 
Nevertheless TC always goes through the DirResourceSet running the 
expensive getCanonicalPath(), returning an EmptyResource and then 
looking for the class and finding it in one of the jar file resources. 
This happens about 5000 times (due to the number of classes to load).

I know that we have to do this in general, because WEB-INF/classes have 
precedence over WEB-INF/lib, but maybe we could optimize in the case we 
are looking for a class but WEB-INF/classes does not even exist? Would 
this be a reasonable general optimization?

Unfortunately the ResourceSet classes can not be easily extended. Since 
most of their fields are private, one would have to fork lots of code. 
It would be much easier to add the feature to the existing implementations.

Regards,

Rainer

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message