From 5a3d0c6e11d9eee40e8134c2efc8fcf6485ce7c5 Mon Sep 17 00:00:00 2001 From: Narayan Kamath Date: Wed, 9 Nov 2016 15:35:18 +0000 Subject: [PATCH] Allow lazy preloading of zygote resources. Add a flag that controls resource preloading. If set, the zygote waits until the first fork request to preload resources. When applied to the secondary zygote, this approach appears to save between 500-800ms of boot time once the webview RELRO step that uses the 32 bit zygote is deferred. Test: Manual Bug: 32735001 Change-Id: Id387b7132d052fa51b9c25f0142fcd546b99662d --- .../android/internal/os/ZygoteConnection.java | 2 ++ .../com/android/internal/os/ZygoteInit.java | 32 +++++++++++++++---- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 39cb464de56c0..e9e642a58a333 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -171,6 +171,8 @@ class ZygoteConnection { return handleAbiListQuery(); } + ZygoteInit.maybePreload(); + if (parsedArgs.preloadPackage != null) { return handlePreloadPackage(parsedArgs.preloadPackage, parsedArgs.preloadPackageLibs); diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index c88e9da49c8eb..f47784ee7c03a 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -112,6 +112,8 @@ public class ZygoteInit { private static final int ROOT_UID = 0; private static final int ROOT_GID = 0; + private static boolean sPreloadComplete; + static void preload(BootTimingsTraceLog bootTimingsTraceLog) { Log.d(TAG, "begin preload"); bootTimingsTraceLog.traceBegin("BeginIcuCachePinning"); @@ -134,6 +136,15 @@ public class ZygoteInit { endIcuCachePinning(); warmUpJcaProviders(); Log.d(TAG, "end preload"); + + sPreloadComplete = true; + } + + public static void maybePreload() { + if (!sPreloadComplete) { + Log.i(TAG, "Lazily preloading resources."); + preload(new BootTimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK)); + } } private static void beginIcuCachePinning() { @@ -660,9 +671,12 @@ public class ZygoteInit { boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; + boolean enableLazyPreload = false; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; + } else if ("--enable-lazy-preload".equals(argv[i])) { + enableLazyPreload = true; } else if (argv[i].startsWith(ABI_LIST_ARG)) { abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { @@ -677,13 +691,17 @@ public class ZygoteInit { } zygoteServer.registerServerSocket(socketName); - bootTimingsTraceLog.traceBegin("ZygotePreload"); - EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, - SystemClock.uptimeMillis()); - preload(bootTimingsTraceLog); - EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, - SystemClock.uptimeMillis()); - bootTimingsTraceLog.traceEnd(); // ZygotePreload + // In some configurations, we avoid preloading resources and classes eagerly. + // In such cases, we will preload things prior to our first fork. + if (!enableLazyPreload) { + bootTimingsTraceLog.traceBegin("ZygotePreload"); + EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, + SystemClock.uptimeMillis()); + preload(bootTimingsTraceLog); + EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, + SystemClock.uptimeMillis()); + bootTimingsTraceLog.traceEnd(); // ZygotePreload + } // Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot();