19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.BufferedWriter; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream; 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStreamWriter; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.Writer; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.nio.charset.Charset; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.TreeSet; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 279d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * Writes /frameworks/base/preloaded-classes. Also updates 289d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * {@link LoadedClass#preloaded} fields and writes over compiled log file. 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class WritePreloadedClassFile { 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee /** 339d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * Preload any class that take longer to load than MIN_LOAD_TIME_MICROS us. 349d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee */ 359d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee static final int MIN_LOAD_TIME_MICROS = 1250; 369d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee 37eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson /** 38eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson * Preload any class that was loaded by at least MIN_PROCESSES processes. 39eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson */ 40eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson static final int MIN_PROCESSES = 10; 41eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson 429d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee public static void main(String[] args) throws IOException, 439d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee ClassNotFoundException { 442e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee if (args.length != 1) { 452e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee System.err.println("Usage: WritePreloadedClassFile [compiled log]"); 462e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee System.exit(-1); 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 482e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee String rootFile = args[0]; 492e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee Root root = Root.fromFile(rootFile); 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 512e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee // No classes are preloaded to start. 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (LoadedClass loadedClass : root.loadedClasses.values()) { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loadedClass.preloaded = false; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 562e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee // Open preloaded-classes file for output. 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Writer out = new BufferedWriter(new OutputStreamWriter( 589d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee new FileOutputStream(Policy.PRELOADED_CLASS_FILE), 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Charset.forName("US-ASCII"))); 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee out.write("# Classes which are preloaded by" 629d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee + " com.android.internal.os.ZygoteInit.\n"); 639d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee out.write("# Automatically generated by frameworks/base/tools/preload/" 649d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee + WritePreloadedClassFile.class.getSimpleName() + ".java.\n"); 659d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee out.write("# MIN_LOAD_TIME_MICROS=" + MIN_LOAD_TIME_MICROS + "\n"); 66eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson out.write("# MIN_PROCESSES=" + MIN_PROCESSES + "\n"); 679d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee 689d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee /* 699d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * The set of classes to preload. We preload a class if: 709d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * 719d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * a) it's loaded in the bootclasspath (i.e., is a system class) 729d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * b) it takes > MIN_LOAD_TIME_MICROS us to load, and 739d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * c) it's loaded by more than one process, or it's loaded by an 749d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * application (i.e., not a long running service) 759d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee */ 762e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee Set<LoadedClass> toPreload = new TreeSet<LoadedClass>(); 772e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee 789d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee // Preload classes that were loaded by at least 2 processes. Hopefully, 799d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee // the memory associated with these classes will be shared. 802e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee for (LoadedClass loadedClass : root.loadedClasses.values()) { 819d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee Set<String> names = loadedClass.processNames(); 82eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson if (!Policy.isPreloadable(loadedClass)) { 83eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson continue; 84eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson } 85eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson 86eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson if (names.size() >= MIN_PROCESSES || 87eaca10e2d0a61c482b6a1799ca9f51d8f67482cbJesse Wilson (loadedClass.medianTimeMicros() > MIN_LOAD_TIME_MICROS && names.size() > 1)) { 882e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee toPreload.add(loadedClass); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee int initialSize = toPreload.size(); 939d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee System.out.println(initialSize 949d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee + " classses were loaded by more than one app."); 959d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee 969d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee // Preload eligable classes from applications (not long-running 979d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee // services). 982e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee for (Proc proc : root.processes.values()) { 999d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee if (proc.fromZygote() && !Policy.isService(proc.name)) { 1009d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee for (Operation operation : proc.operations) { 1019d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee LoadedClass loadedClass = operation.loadedClass; 1029d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee if (shouldPreload(loadedClass)) { 1039d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee toPreload.add(loadedClass); 1049d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee } 1059d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee } 1069d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee } 1072e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee } 1082e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee 1099d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee System.out.println("Added " + (toPreload.size() - initialSize) 1109d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee + " more to speed up applications."); 1112e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee 1129d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee System.out.println(toPreload.size() 1139d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee + " total classes will be preloaded."); 1149d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee 1159d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee // Make classes that were implicitly loaded by the zygote explicit. 1162e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee // This adds minimal overhead but avoid confusion about classes not 1172e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee // appearing in the list. 1189d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee addAllClassesFrom("zygote", root, toPreload); 1192e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee 1202e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee for (LoadedClass loadedClass : toPreload) { 1219d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee out.write(loadedClass.name + "\n"); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.close(); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update data to reflect LoadedClass.preloaded changes. 1272e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee for (LoadedClass loadedClass : toPreload) { 1282e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee loadedClass.preloaded = true; 1292e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee } 1302e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee root.toFile(rootFile); 1312e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee } 1322e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee 1339d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee private static void addAllClassesFrom(String processName, Root root, 1349d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee Set<LoadedClass> toPreload) { 1352e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee for (Proc proc : root.processes.values()) { 1369d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee if (proc.name.equals(processName)) { 1372e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee for (Operation operation : proc.operations) { 1389d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee boolean preloadable 1399d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee = Policy.isPreloadable(operation.loadedClass); 1409d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee if (preloadable) { 1412e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee toPreload.add(operation.loadedClass); 1422e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee } 1432e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee } 1442e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee } 1452e93f65cab0b4b21a1285b83e985559325e87a3aBob Lee } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee 1489d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee /** 1499d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee * Returns true if the class should be preloaded. 1509d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee */ 1519d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee private static boolean shouldPreload(LoadedClass clazz) { 1529d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee return Policy.isPreloadable(clazz) 1539d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee && clazz.medianTimeMicros() > MIN_LOAD_TIME_MICROS; 1549d2d6e14b0932b6a74e01f393d5efed61458941bBob Lee } 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 156