Pre-initialize ResourceOracleImpl's classpaths in parallel with other startup
tasks.
http://gwt-code-reviews.appspot.com/1265801/show
Review by: conroy@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9512 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/DevMode.java b/dev/core/src/com/google/gwt/dev/DevMode.java
index 8bcdcca..4bc6b14 100644
--- a/dev/core/src/com/google/gwt/dev/DevMode.java
+++ b/dev/core/src/com/google/gwt/dev/DevMode.java
@@ -23,6 +23,7 @@
import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
import com.google.gwt.dev.cfg.ModuleDef;
+import com.google.gwt.dev.resource.impl.ResourceOracleImpl;
import com.google.gwt.dev.shell.jetty.JettyLauncher;
import com.google.gwt.dev.ui.RestartServerCallback;
import com.google.gwt.dev.ui.RestartServerEvent;
@@ -411,6 +412,21 @@
}
@Override
+ protected boolean doStartup() {
+ // Background scan the classpath to warm the cache.
+ Thread scanThread = new Thread(new Runnable() {
+ public void run() {
+ ResourceOracleImpl.preload(getTopLogger());
+ }
+ });
+ scanThread.setDaemon(true);
+ scanThread.setPriority((Thread.MIN_PRIORITY + Thread.NORM_PRIORITY) / 2);
+ scanThread.start();
+
+ return super.doStartup();
+ }
+
+ @Override
protected int doStartUpServer() {
// Create the war directory if it doesn't exist
File warDir = options.getWarDir();
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java b/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
index 31b5b44..d6dcb5b 100644
--- a/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/ResourceOracleImpl.java
@@ -172,6 +172,30 @@
}
/**
+ * Preinitializes the classpath from the thread default {@link ClassLoader}.
+ */
+ public static void preload(TreeLogger logger) {
+ preload(logger, Thread.currentThread().getContextClassLoader());
+ }
+
+ /**
+ * Preinitializes the classpath for a given {@link ClassLoader}.
+ */
+ public static void preload(TreeLogger logger, ClassLoader classLoader) {
+ Event resourceOracle = SpeedTracerLogger.start(
+ CompilerEventType.RESOURCE_ORACLE, "phase", "preload");
+ List<ClassPathEntry> entries = getAllClassPathEntries(logger, classLoader);
+ for (ClassPathEntry entry : entries) {
+ // We only handle pre-indexing jars, the file system could change.
+ if (entry instanceof ZipFileClassPathEntry) {
+ ZipFileClassPathEntry zpe = (ZipFileClassPathEntry) entry;
+ zpe.index(logger);
+ }
+ }
+ resourceOracle.end();
+ }
+
+ /**
* Rescans the associated paths to recompute the available resources.
*
* TODO(conroy,scottb): This synchronization could be improved upon to allow
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
index 5194594..be2fc8f 100644
--- a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
@@ -90,11 +90,7 @@
@Override
public Map<AbstractResource, PathPrefix> findApplicableResources(
TreeLogger logger, PathPrefixSet pathPrefixSet) {
- // Never re-index.
- if (allZipFileResources == null) {
- allZipFileResources = buildIndex(logger);
- }
-
+ index(logger);
ZipFileSnapshot snapshot = cachedSnapshots.get(pathPrefixSet);
if (snapshot == null || snapshot.prefixSetSize != pathPrefixSet.getSize()) {
snapshot = new ZipFileSnapshot(pathPrefixSet.getSize(),
@@ -113,6 +109,13 @@
return zipFile;
}
+ synchronized void index(TreeLogger logger) {
+ // Never re-index.
+ if (allZipFileResources == null) {
+ allZipFileResources = buildIndex(logger);
+ }
+ }
+
private Set<ZipFileResource> buildIndex(TreeLogger logger) {
logger = Messages.BUILDING_INDEX.branch(logger, zipFile.getName(), null);