1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Set;
import java.util.TreeSet;
/**
* Writes /frameworks/base/preloaded-classes. Also updates
* {@link LoadedClass#preloaded} fields and writes over compiled log file.
*/
public class WritePreloadedClassFile {
/**
* Preload any class that take longer to load than MIN_LOAD_TIME_MICROS us.
*/
static final int MIN_LOAD_TIME_MICROS = 1250;
/**
* Preload any class that was loaded by at least MIN_PROCESSES processes.
*/
static final int MIN_PROCESSES = 10;
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.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/"
+ WritePreloadedClassFile.class.getSimpleName() + ".java.\n");
out.write("# MIN_LOAD_TIME_MICROS=" + MIN_LOAD_TIME_MICROS + "\n");
out.write("# MIN_PROCESSES=" + MIN_PROCESSES + "\n");
/*
* 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>();
// 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 (!Policy.isPreloadable(loadedClass)) {
continue;
}
if (names.size() >= MIN_PROCESSES ||
(loadedClass.medianTimeMicros() > MIN_LOAD_TIME_MICROS && names.size() > 1)) {
toPreload.add(loadedClass);
}
}
int initialSize = toPreload.size();
System.out.println(initialSize
+ " classses were loaded by more than one app.");
// 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);
}
}
}
}
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();
// Update data to reflect LoadedClass.preloaded changes.
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;
}
}
|