diff options
author | 2016-05-09 16:55:36 +0100 | |
---|---|---|
committer | 2016-05-18 11:15:11 +0100 | |
commit | 41c9dc3b6938c5674c88ef4bc27b3d95f56efebe (patch) | |
tree | a8148e19835f3d26a0f15a1e5e8667bf84527fd3 | |
parent | aa733e0b41e4e15908a4c89e935f824cc5908b4d (diff) |
Add support for ICU data pinning in the Zygote
Upstream ICU caches use SoftReferences. On Android this means
that useful cached data initialized in the Zygote are "lost" when
the Zygote GCs and cannot be shared with apps. This change makes use
of an Android patch to ICU to ensure References created during
Zygote initialization are "strong". i.e. they are never collected.
This prevents them being GCd and ensures they can be shared between
applications.
After switching ICU to use strong references, this change
also creates DecimalFormatSymbols objects for common ULocales
(ROOT, US and the user's default, if different). DecimalFormatSymbols
makes use of an ICU Reference cache and this alone has been shown to
improve the construction time of java.text.DecimalFormat by 1-1.5
milliseconds on a Seed device. This saving applies the first time one
is created in each app for each locale, and again if SoftReferences
have been cleared.
The cost to the heap size of the Zygote has been measured at ~107k.
This value will change as more caches are switched to use the new
CacheValue class.
Formatting is typically performed on the UI thread and the intention
of this change is to reduce app start up time and jank in apps like
the Dialer which do a lot of formatting when scrolling lists. The
change may also enable more virtual memory page-sharing between
apps, though this is not the specific goal.
Bug: 28326526
Change-Id: Ia2c73f6525f05b1aa81e57a31eed1616decf6bb5
-rw-r--r-- | core/java/com/android/internal/os/ZygoteInit.java | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 1440e5fb559d..83ffb54af583 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -22,6 +22,9 @@ import static android.system.OsConstants.S_IRWXO; import android.content.res.Resources; import android.content.res.TypedArray; +import android.icu.impl.CacheValue; +import android.icu.text.DecimalFormatSymbols; +import android.icu.util.ULocale; import android.net.LocalServerSocket; import android.opengl.EGL14; import android.os.Process; @@ -181,6 +184,9 @@ public class ZygoteInit { static void preload() { Log.d(TAG, "begin preload"); + Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning"); + beginIcuCachePinning(); + Trace.traceEnd(Trace.TRACE_TAG_DALVIK); Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses"); preloadClasses(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); @@ -195,10 +201,34 @@ public class ZygoteInit { // Ask the WebViewFactory to do any initialization that must run in the zygote process, // for memory sharing purposes. WebViewFactory.prepareWebViewInZygote(); + endIcuCachePinning(); warmUpJcaProviders(); Log.d(TAG, "end preload"); } + private static void beginIcuCachePinning() { + // Pin ICU data in memory from this point that would normally be held by soft references. + // Without this, any references created immediately below or during class preloading + // would be collected when the Zygote GC runs in gcAndFinalize(). + Log.i(TAG, "Installing ICU cache reference pinning..."); + + CacheValue.setStrength(CacheValue.Strength.STRONG); + + Log.i(TAG, "Preloading ICU data..."); + // Explicitly exercise code to cache data apps are likely to need. + ULocale[] localesToPin = { ULocale.ROOT, ULocale.US, ULocale.getDefault() }; + for (ULocale uLocale : localesToPin) { + new DecimalFormatSymbols(uLocale); + } + } + + private static void endIcuCachePinning() { + // All cache references created by ICU from this point will be soft. + CacheValue.setStrength(CacheValue.Strength.SOFT); + + Log.i(TAG, "Uninstalled ICU cache reference pinning..."); + } + private static void preloadSharedLibraries() { Log.i(TAG, "Preloading shared libraries..."); System.loadLibrary("android"); |