Details
-
Improvement
-
Status: Closed
-
Major
-
Resolution: Fixed
-
None
-
None
Description
While benchmarking tapestry framework with concurency level = 4 I found lock contention in AssetSourceImpl.java.
Lock looks as follows:
java.lang.Thread.State: BLOCKED (on object monitor)
at java.util.zip.ZipFile.getEntry(ZipFile.java:304)
- locked <0x0000000711ee6800> (a java.util.jar.JarFile)
at java.util.jar.JarFile.getEntry(JarFile.java:226)
at java.util.jar.JarFile.getJarEntry(JarFile.java:209)
at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:840)
at sun.misc.URLClassPath$JarLoader.findResource(URLClassPath.java:818)
at sun.misc.URLClassPath.findResource(URLClassPath.java:176)
at java.net.URLClassLoader$2.run(URLClassLoader.java:551)
at java.net.URLClassLoader$2.run(URLClassLoader.java:549)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findResource(URLClassLoader.java:548)
at java.lang.ClassLoader.getResource(ClassLoader.java:1139)
at java.lang.ClassLoader.getResource(ClassLoader.java:1134)
at org.apache.catalina.loader.WebappClassLoader.getResource(WebappClassLoader.java:1417)
at org.apache.tapestry5.ioc.internal.util.ClasspathResource.resolveURL(ClasspathResource.java:79)
at org.apache.tapestry5.ioc.internal.util.ClasspathResource.toURL(ClasspathResource.java:61)
at org.apache.tapestry5.ioc.internal.util.AbstractResource.computeExists(AbstractResource.java:236)
at org.apache.tapestry5.ioc.internal.util.AbstractResource.exists(AbstractResource.java:218)
at org.apache.tapestry5.ioc.internal.util.AbstractResource.findLocalizedResource(AbstractResource.java:177)
at org.apache.tapestry5.ioc.internal.util.AbstractResource.populateLocalizationCache(AbstractResource.java:159)
at org.apache.tapestry5.ioc.internal.util.AbstractResource.forLocale(AbstractResource.java:136)
at org.apache.tapestry5.internal.services.AssetSourceImpl.getLocalizedAssetFromResource(AssetSourceImpl.java:134)
at org.apache.tapestry5.internal.services.AssetSourceImpl.getAssetInLocale(AssetSourceImpl.java:107)
at org.apache.tapestry5.internal.services.AssetSourceImpl.getAsset(AssetSourceImpl.java:87)
at $AssetSource_369c373aab0b9a.getAsset(Unknown Source)
at org.apache.tapestry5.internal.services.javascript.CoreJavaScriptStack.getJavaScriptLibraries(CoreJavaScriptStack.java:154)
Here is a cache to prevent lock contention, but I'm not sure whether it works properly.
private final Map<Resource, SoftReference<Asset>> cache = new WeakHashMap<Resource, SoftReference<Asset>>();
Here the problem is that Resource is used as a key.
So the cache entry will be removed as soon as key is available for garbage collection.
Resources aren't always long-lived objects.
For example resources produced by AssetSourceImpl.findResource(Resource baseResource, String path) has a very short lifecycle.
It would be good to use SoftHashMap instead of WeakHashMap here, but it is not included in standard Java.
To check my assumption I created cache based on ConcurrentHashMap instead of WeakHashMap. As result of it lock contention disappeared and overall performance increased.