Zygote: Add support for explicit preloading of resources.

Add a --preload-default command that instructs the zygote to preload
resources. The command is a no-op if resources have already been
preloaded.

Test: manual.
Change-Id: I4a846a7d911fa929af472d9071ffbff6df424176
This commit is contained in:
Narayan Kamath
2017-02-06 20:24:08 +00:00
parent 83e0faf2cc
commit 669afcc9d0
4 changed files with 80 additions and 11 deletions

View File

@@ -506,4 +506,24 @@ public class ZygoteProcess {
state.writer.flush();
}
}
/**
* Instructs the zygote to preload the default set of classes and resources. Returns
* {@code true} if a preload was performed as a result of this call, and {@code false}
* otherwise. The latter usually means that the zygote eagerly preloaded at startup
* or due to a previous call to {@code preloadDefault}. Note that this call is synchronous.
*/
public boolean preloadDefault(String abi) throws ZygoteStartFailedEx, IOException {
synchronized (mLock) {
ZygoteState state = openZygoteSocketIfNeeded(abi);
// Each query starts with the argument count (1 in this case)
state.writer.write("1");
state.writer.newLine();
state.writer.write("--preload-default");
state.writer.newLine();
state.writer.flush();
return (state.inputStream.readInt() == 0);
}
}
}

View File

@@ -55,8 +55,15 @@ class WebViewZygoteInit {
}
@Override
protected void maybePreload() {
// Do nothing, we don't need to call ZygoteInit.maybePreload() for the WebView zygote.
protected void preload() {
// Nothing to preload by default.
}
@Override
protected boolean isPreloadComplete() {
// Webview zygotes don't preload any classes or resources or defaults, all of their
// preloading is package specific.
return true;
}
@Override

View File

@@ -171,7 +171,9 @@ class ZygoteConnection {
return handleAbiListQuery();
}
maybePreload();
if (parsedArgs.preloadDefault) {
return handlePreload();
}
if (parsedArgs.preloadPackage != null) {
return handlePreloadPackage(parsedArgs.preloadPackage,
@@ -282,8 +284,34 @@ class ZygoteConnection {
}
}
protected void maybePreload() {
ZygoteInit.maybePreload();
/**
* Preloads resources if the zygote is in lazily preload mode. Writes the result of the
* preload operation; {@code 0} when a preload was initiated due to this request and {@code 1}
* if no preload was initiated. The latter implies that the zygote is not configured to load
* resources lazy or that the zygote has already handled a previous request to handlePreload.
*/
private boolean handlePreload() {
try {
if (isPreloadComplete()) {
mSocketOutStream.writeInt(1);
} else {
preload();
mSocketOutStream.writeInt(0);
}
return false;
} catch (IOException ioe) {
Log.e(TAG, "Error writing to command socket", ioe);
return true;
}
}
protected void preload() {
ZygoteInit.lazyPreload();
}
protected boolean isPreloadComplete() {
return ZygoteInit.isPreloadComplete();
}
protected boolean handlePreloadPackage(String packagePath, String libsPath) {
@@ -401,6 +429,13 @@ class ZygoteConnection {
String preloadPackage;
String preloadPackageLibs;
/**
* Whether this is a request to start preloading the default resources and classes.
* This argument only makes sense when the zygote is in lazy preload mode (i.e, when
* it's started with --enable-lazy-preload).
*/
boolean preloadDefault;
/**
* Constructs instance and parses args
* @param args zygote command-line args
@@ -564,6 +599,8 @@ class ZygoteConnection {
} else if (arg.equals("--preload-package")) {
preloadPackage = args[++curArg];
preloadPackageLibs = args[++curArg];
} else if (arg.equals("--preload-default")) {
preloadDefault = true;
} else {
break;
}
@@ -578,7 +615,7 @@ class ZygoteConnection {
throw new IllegalArgumentException(
"Unexpected arguments after --preload-package.");
}
} else {
} else if (!preloadDefault) {
if (!seenRuntimeArgs) {
throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
}

View File

@@ -51,6 +51,7 @@ import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.util.Preconditions;
import dalvik.system.DexFile;
import dalvik.system.PathClassLoader;
import dalvik.system.VMRuntime;
@@ -146,11 +147,11 @@ public class ZygoteInit {
sPreloadComplete = true;
}
public static void maybePreload() {
if (!sPreloadComplete) {
Log.i(TAG, "Lazily preloading resources.");
preload(new BootTimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK));
}
public static void lazyPreload() {
Preconditions.checkState(!sPreloadComplete);
Log.i(TAG, "Lazily preloading resources.");
preload(new BootTimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK));
}
private static void beginIcuCachePinning() {
@@ -785,6 +786,10 @@ public class ZygoteInit {
}
}
static boolean isPreloadComplete() {
return sPreloadComplete;
}
/**
* Class not instantiable.
*/