diff options
Diffstat (limited to 'tools/preload/WritePreloadedClassFile.java')
| -rw-r--r-- | tools/preload/WritePreloadedClassFile.java | 144 |
1 files changed, 93 insertions, 51 deletions
diff --git a/tools/preload/WritePreloadedClassFile.java b/tools/preload/WritePreloadedClassFile.java index d87b1f056a01..96c539bb727e 100644 --- a/tools/preload/WritePreloadedClassFile.java +++ b/tools/preload/WritePreloadedClassFile.java @@ -20,83 +20,125 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; import java.util.Set; import java.util.TreeSet; /** - * Writes /frameworks/base/preloaded-classes. Also updates LoadedClass.preloaded - * fields and writes over compiled log file. + * Writes /frameworks/base/preloaded-classes. Also updates + * {@link LoadedClass#preloaded} fields and writes over compiled log file. */ public class WritePreloadedClassFile { - public static void main(String[] args) throws IOException, ClassNotFoundException { - - // Process command-line arguments first - List<String> wiredProcesses = new ArrayList<String>(); - String inputFileName = null; - int argOffset = 0; - try { - while ("--preload-all-process".equals(args[argOffset])) { - argOffset++; - wiredProcesses.add(args[argOffset++]); - } - - inputFileName = args[argOffset++]; - } catch (RuntimeException e) { - System.err.println("Usage: WritePreloadedClassFile " + - "[--preload-all-process process-name] " + - "[compiled log file]"); - System.exit(0); - } + /** + * Preload any class that take longer to load than MIN_LOAD_TIME_MICROS us. + */ + static final int MIN_LOAD_TIME_MICROS = 1250; - Root root = Root.fromFile(inputFileName); + public static void main(String[] args) throws IOException, + ClassNotFoundException { + if (args.length != 1) { + System.err.println("Usage: WritePreloadedClassFile [compiled log]"); + System.exit(-1); + } + String rootFile = args[0]; + Root root = Root.fromFile(rootFile); + // No classes are preloaded to start. for (LoadedClass loadedClass : root.loadedClasses.values()) { loadedClass.preloaded = false; } + // Open preloaded-classes file for output. Writer out = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(Policy.getPreloadedClassFileName()), + new FileOutputStream(Policy.PRELOADED_CLASS_FILE), Charset.forName("US-ASCII"))); - out.write("# Classes which are preloaded by com.android.internal.os.ZygoteInit.\n"); - out.write("# Automatically generated by /frameworks/base/tools/preload.\n"); - out.write("# percent=" + Proc.PERCENTAGE_TO_PRELOAD + ", weight=" - + ClassRank.SEQUENCE_WEIGHT - + ", bucket_size=" + ClassRank.BUCKET_SIZE - + "\n"); - for (String wiredProcess : wiredProcesses) { - out.write("# forcing classes loaded by: " + wiredProcess + "\n"); - } + out.write("# Classes which are preloaded by" + + " com.android.internal.os.ZygoteInit.\n"); + out.write("# Automatically generated by frameworks/base/tools/preload/" + + WritePreloadedClassFile.class.getSimpleName() + ".java.\n"); + out.write("# MIN_LOAD_TIME_MICROS=" + MIN_LOAD_TIME_MICROS + "\n"); - Set<LoadedClass> highestRanked = new TreeSet<LoadedClass>(); - for (Proc proc : root.processes.values()) { - // test to see if this is one of the wired-down ("take all classes") processes - boolean isWired = wiredProcesses.contains(proc.name); - - List<LoadedClass> highestForProc = proc.highestRankedClasses(isWired); + /* + * The set of classes to preload. We preload a class if: + * + * a) it's loaded in the bootclasspath (i.e., is a system class) + * b) it takes > MIN_LOAD_TIME_MICROS us to load, and + * c) it's loaded by more than one process, or it's loaded by an + * application (i.e., not a long running service) + */ + Set<LoadedClass> toPreload = new TreeSet<LoadedClass>(); - System.out.println(proc.name + ": " + highestForProc.size()); + // Preload classes that were loaded by at least 2 processes. Hopefully, + // the memory associated with these classes will be shared. + for (LoadedClass loadedClass : root.loadedClasses.values()) { + Set<String> names = loadedClass.processNames(); + if (shouldPreload(loadedClass) && names.size() > 1) { + toPreload.add(loadedClass); + } + } + + int initialSize = toPreload.size(); + System.out.println(initialSize + + " classses were loaded by more than one app."); - for (LoadedClass loadedClass : highestForProc) { - loadedClass.preloaded = true; + // Preload eligable classes from applications (not long-running + // services). + for (Proc proc : root.processes.values()) { + if (proc.fromZygote() && !Policy.isService(proc.name)) { + for (Operation operation : proc.operations) { + LoadedClass loadedClass = operation.loadedClass; + if (shouldPreload(loadedClass)) { + toPreload.add(loadedClass); + } + } } - highestRanked.addAll(highestForProc); } - for (LoadedClass loadedClass : highestRanked) { - out.write(loadedClass.name); - out.write('\n'); + System.out.println("Added " + (toPreload.size() - initialSize) + + " more to speed up applications."); + + System.out.println(toPreload.size() + + " total classes will be preloaded."); + + // Make classes that were implicitly loaded by the zygote explicit. + // This adds minimal overhead but avoid confusion about classes not + // appearing in the list. + addAllClassesFrom("zygote", root, toPreload); + + for (LoadedClass loadedClass : toPreload) { + out.write(loadedClass.name + "\n"); } out.close(); - System.out.println(highestRanked.size() - + " classes will be preloaded."); - // Update data to reflect LoadedClass.preloaded changes. - root.toFile(inputFileName); + for (LoadedClass loadedClass : toPreload) { + loadedClass.preloaded = true; + } + root.toFile(rootFile); + } + + private static void addAllClassesFrom(String processName, Root root, + Set<LoadedClass> toPreload) { + for (Proc proc : root.processes.values()) { + if (proc.name.equals(processName)) { + for (Operation operation : proc.operations) { + boolean preloadable + = Policy.isPreloadable(operation.loadedClass); + if (preloadable) { + toPreload.add(operation.loadedClass); + } + } + } + } + } + + /** + * Returns true if the class should be preloaded. + */ + private static boolean shouldPreload(LoadedClass clazz) { + return Policy.isPreloadable(clazz) + && clazz.medianTimeMicros() > MIN_LOAD_TIME_MICROS; } } |