Revision: 9885
Author: scheg...@google.com
Date: Wed Mar 23 12:56:08 2011
Log: Using cached ZipFileClassPathEntry objects.
While this does not give benefits for DevMode, which parses jar files only
once, GWT Designer does this many times.
This gives about 15% speed up in GWT Designer.
Initial.
-------------
Parsing...done: 4775
refresh: 296
palette: 114
Parsing...done: 2445
refresh: 274
palette: 38
Parsing...done: 2396
refresh: 272
palette: 37
Cache ZipFileClassPathEntry
-------------
Parsing...done: 4299
refresh: 304
palette: 116
Parsing...done: 2161
refresh: 277
palette: 41
Parsing...done: 2087
refresh: 270
palette: 38
Review at http://gwt-code-reviews.appspot.com/1388803
http://code.google.com/p/google-web-toolkit/source/detail?r=9885
Modified:
/trunk/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
/trunk/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
/trunk/dev/core/test/com/google/gwt/dev/resource/impl/AbstractResourceOrientedTestBase.java
/trunk/dev/core/test/com/google/gwt/dev/resource/impl/ResourceOracleImplTest.java
=======================================
---
/trunk/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
Thu Feb 10 07:58:19 2011
+++
/trunk/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
Wed Mar 23 12:56:08 2011
@@ -156,14 +156,14 @@
if (f.isDirectory()) {
return new DirectoryClassPathEntry(f);
} else if (f.isFile() && lowerCaseFileName.endsWith(".jar")) {
- return new ZipFileClassPathEntry(f);
+ return ZipFileClassPathEntry.get(f);
} else if (f.isFile() && lowerCaseFileName.endsWith(".zip")) {
- return new ZipFileClassPathEntry(f);
+ return ZipFileClassPathEntry.get(f);
} else {
// It's a file ending in neither jar nor zip, speculatively try to
// open as jar/zip anyway.
try {
- return new ZipFileClassPathEntry(f);
+ return ZipFileClassPathEntry.get(f);
} catch (Exception ignored) {
}
logger.log(TreeLogger.TRACE, "Unexpected entry in classpath; " + f
=======================================
---
/trunk/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
Fri Mar 18 10:49:05 2011
+++
/trunk/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
Wed Mar 23 12:56:08 2011
@@ -22,6 +22,10 @@
import com.google.gwt.dev.util.collect.Sets;
import com.google.gwt.dev.util.msg.Message1String;
+import org.apache.commons.collections.map.AbstractReferenceMap;
+import org.apache.commons.collections.map.ReferenceIdentityMap;
+import org.apache.commons.collections.map.ReferenceMap;
+
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
@@ -65,19 +69,47 @@
this.cachedAnswers = cachedAnswers;
}
}
+
+ /**
+ * Memory-sensitive cache of indexed {@link ZipFileClassPathEntry}s. URI
of file is most probably
+ * not referenced anywhere else, so we use hard reference, and soft
reference on
+ * {@link ZipFileClassPathEntry} allows its clearing in response to
memory demand.
+ */
+ @SuppressWarnings("unchecked")
+ private static final Map<String, ZipFileClassPathEntry> entryCache = new
ReferenceMap(
+ AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT);
+
+ /**
+ * @return the {@link ZipFileClassPathEntry} instance for given jar or
zip
+ * file, may be shared with other users.
+ */
+ public static synchronized ZipFileClassPathEntry get(File zipFile)
throws IOException {
+ String location = zipFile.toURI().toString();
+ ZipFileClassPathEntry entry = entryCache.get(location);
+ if (entry == null) {
+ entry = new ZipFileClassPathEntry(zipFile);
+ entryCache.put(location, entry);
+ }
+ return entry;
+ }
private Set<ZipFileResource> allZipFileResources;
/**
- * Currently gwt has just 2 ResourceOracles.
+ * The lifetime of the {@link PathPrefixSet} pins the life time of the
associated
+ * {@link ZipFileSnapshot}; this is because the {@link PathPrefixSet} is
referenced from module,
+ * and {@link ZipFileSnapshot} is not referenced anywhere outside of
{@link ZipFileClassPathEntry}
+ * . When the module dies, the {@link ZipFileSnapshot} needs to die also.
*/
- private final Map<PathPrefixSet, ZipFileSnapshot> cachedSnapshots = new
IdentityHashMap<PathPrefixSet, ZipFileSnapshot>();
+ @SuppressWarnings("unchecked")
+ private final Map<PathPrefixSet, ZipFileSnapshot> cachedSnapshots = new
ReferenceIdentityMap(
+ AbstractReferenceMap.WEAK, AbstractReferenceMap.HARD, true);
private final String location;
private final ZipFile zipFile;
- public ZipFileClassPathEntry(File zipFile) throws IOException {
+ private ZipFileClassPathEntry(File zipFile) throws IOException {
assert zipFile.isAbsolute();
this.zipFile = new ZipFile(zipFile);
this.location = zipFile.toURI().toString();
@@ -87,7 +119,7 @@
* Indexes the zip file on-demand, and only once over the life of the
process.
*/
@Override
- public Map<AbstractResource, PathPrefix> findApplicableResources(
+ public synchronized Map<AbstractResource, PathPrefix>
findApplicableResources(
TreeLogger logger, PathPrefixSet pathPrefixSet) {
index(logger);
ZipFileSnapshot snapshot = cachedSnapshots.get(pathPrefixSet);
=======================================
---
/trunk/dev/core/test/com/google/gwt/dev/resource/impl/AbstractResourceOrientedTestBase.java
Wed Aug 4 09:54:49 2010
+++
/trunk/dev/core/test/com/google/gwt/dev/resource/impl/AbstractResourceOrientedTestBase.java
Wed Mar 23 12:56:08 2011
@@ -193,12 +193,12 @@
protected ClassPathEntry getClassPathEntry1AsJar() throws IOException,
URISyntaxException {
File file =
findFile("com/google/gwt/dev/resource/impl/testdata/cpe1.jar");
- return new ExcludeSvnClassPathEntry(new ZipFileClassPathEntry(file));
+ return new ExcludeSvnClassPathEntry(ZipFileClassPathEntry.get(file));
}
protected ClassPathEntry getClassPathEntry1AsZip() throws IOException,
URISyntaxException {
File file =
findFile("com/google/gwt/dev/resource/impl/testdata/cpe1.zip");
- return new ExcludeSvnClassPathEntry(new ZipFileClassPathEntry(file));
+ return new ExcludeSvnClassPathEntry(ZipFileClassPathEntry.get(file));
}
protected ClassPathEntry getClassPathEntry1AsMock() {
@@ -214,12 +214,12 @@
protected ClassPathEntry getClassPathEntry2AsJar() throws
URISyntaxException,
IOException {
File file =
findFile("com/google/gwt/dev/resource/impl/testdata/cpe2.jar");
- return new ExcludeSvnClassPathEntry(new ZipFileClassPathEntry(file));
+ return new ExcludeSvnClassPathEntry(ZipFileClassPathEntry.get(file));
}
protected ClassPathEntry getClassPathEntry2AsZip() throws
URISyntaxException, IOException {
File file =
findFile("com/google/gwt/dev/resource/impl/testdata/cpe2.zip");
- return new ExcludeSvnClassPathEntry(new ZipFileClassPathEntry(file));
+ return new ExcludeSvnClassPathEntry(ZipFileClassPathEntry.get(file));
}
protected ClassPathEntry getClassPathEntry2AsMock() {
=======================================
---
/trunk/dev/core/test/com/google/gwt/dev/resource/impl/ResourceOracleImplTest.java
Fri Sep 17 13:02:11 2010
+++
/trunk/dev/core/test/com/google/gwt/dev/resource/impl/ResourceOracleImplTest.java
Wed Mar 23 12:56:08 2011
@@ -193,7 +193,7 @@
URISyntaxException {
TreeLogger logger = createTestTreeLogger();
File jarFile =
findFile("com/google/gwt/dev/resource/impl/testdata/cpe1.jar");
- ClassPathEntry cpe1jar = new ZipFileClassPathEntry(jarFile);
+ ClassPathEntry cpe1jar = ZipFileClassPathEntry.get(jarFile);
// test basic caching
PathPrefixSet pps1 = new PathPrefixSet();
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors