diff options
| -rw-r--r-- | core/java/android/os/Debug.java | 19 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/ZygoteInit.java | 61 |
2 files changed, 79 insertions, 1 deletions
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 5ea5aaedccaf..e73a97e0b04c 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -633,6 +633,25 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo public static final native int getBinderDeathObjectCount(); /** + * Primes the register map cache. + * + * Only works for classes in the bootstrap class loader. Does not + * cause classes to be loaded if they're not already present. + * + * The classAndMethodDesc argument is a concatentation of the VM-internal + * class descriptor, method name, and method descriptor. Examples: + * Landroid/os/Looper;.loop:()V + * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V + * + * @param classAndMethodDesc the method to prepare + * + * @hide + */ + public static final boolean cacheRegisterMap(String classAndMethodDesc) { + return VMDebug.cacheRegisterMap(classAndMethodDesc); + } + + /** * API for gathering and querying instruction counts. * * Example usage: diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index ac8b58934168..fa2bb22b5cbb 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -93,7 +93,26 @@ public class ZygoteInit { /** Controls whether we should preload resources during zygote init. */ private static final boolean PRELOAD_RESOURCES = true; - + + /** + * List of methods we "warm up" in the register map cache. These were + * chosen because they appeared on the stack in GCs in multiple + * applications. + * + * This is in a VM-ready format, to minimize string processing. If a + * class is not already loaded, or a method is not found, the entry + * will be skipped. + * + * This doesn't really merit a separately-generated input file at this + * time. The list is fairly short, and the consequences of failure + * are minor. + */ + private static final String[] REGISTER_MAP_METHODS = { + // (currently not doing any) + //"Landroid/app/Activity;.setContentView:(I)V", + }; + + /** * Invokes a static "main(argv[]) method on class "className". * Converts various failing exceptions into RuntimeExceptions, with @@ -319,6 +338,45 @@ public class ZygoteInit { } /** + * Pre-caches register maps for methods that are commonly used. + */ + private static void cacheRegisterMaps() { + String failed = null; + int failure; + long startTime = System.nanoTime(); + + failure = 0; + + for (int i = 0; i < REGISTER_MAP_METHODS.length; i++) { + String str = REGISTER_MAP_METHODS[i]; + + if (!Debug.cacheRegisterMap(str)) { + if (failed == null) + failed = str; + failure++; + } + } + + long delta = System.nanoTime() - startTime; + + if (failure == REGISTER_MAP_METHODS.length) { + if (REGISTER_MAP_METHODS.length > 0) { + Log.i(TAG, + "Register map caching failed (precise GC not enabled?)"); + } + return; + } + + Log.i(TAG, "Register map cache: found " + + (REGISTER_MAP_METHODS.length - failure) + " of " + + REGISTER_MAP_METHODS.length + " methods in " + + (delta / 1000000L) + "ms"); + if (failure > 0) { + Log.i(TAG, " First failure: " + failed); + } + } + + /** * Load in commonly used resources, so they can be shared across * processes. * @@ -510,6 +568,7 @@ public class ZygoteInit { EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preloadClasses(); + //cacheRegisterMaps(); preloadResources(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); |