blob: 96c539bb727ed3467cf5e5bc394bf2723658adda [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import java.io.BufferedWriter;
18import java.io.FileOutputStream;
19import java.io.IOException;
20import java.io.OutputStreamWriter;
21import java.io.Writer;
22import java.nio.charset.Charset;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import java.util.Set;
24import java.util.TreeSet;
25
26/**
Bob Lee9d2d6e12009-08-13 14:41:54 -070027 * Writes /frameworks/base/preloaded-classes. Also updates
28 * {@link LoadedClass#preloaded} fields and writes over compiled log file.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029 */
30public class WritePreloadedClassFile {
31
Bob Lee9d2d6e12009-08-13 14:41:54 -070032 /**
33 * Preload any class that take longer to load than MIN_LOAD_TIME_MICROS us.
34 */
35 static final int MIN_LOAD_TIME_MICROS = 1250;
36
37 public static void main(String[] args) throws IOException,
38 ClassNotFoundException {
Bob Lee2e93f652009-08-11 01:16:03 -070039 if (args.length != 1) {
40 System.err.println("Usage: WritePreloadedClassFile [compiled log]");
41 System.exit(-1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042 }
Bob Lee2e93f652009-08-11 01:16:03 -070043 String rootFile = args[0];
44 Root root = Root.fromFile(rootFile);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045
Bob Lee2e93f652009-08-11 01:16:03 -070046 // No classes are preloaded to start.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047 for (LoadedClass loadedClass : root.loadedClasses.values()) {
48 loadedClass.preloaded = false;
49 }
50
Bob Lee2e93f652009-08-11 01:16:03 -070051 // Open preloaded-classes file for output.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 Writer out = new BufferedWriter(new OutputStreamWriter(
Bob Lee9d2d6e12009-08-13 14:41:54 -070053 new FileOutputStream(Policy.PRELOADED_CLASS_FILE),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054 Charset.forName("US-ASCII")));
55
Bob Lee9d2d6e12009-08-13 14:41:54 -070056 out.write("# Classes which are preloaded by"
57 + " com.android.internal.os.ZygoteInit.\n");
58 out.write("# Automatically generated by frameworks/base/tools/preload/"
59 + WritePreloadedClassFile.class.getSimpleName() + ".java.\n");
60 out.write("# MIN_LOAD_TIME_MICROS=" + MIN_LOAD_TIME_MICROS + "\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061
Bob Lee9d2d6e12009-08-13 14:41:54 -070062 /*
63 * The set of classes to preload. We preload a class if:
64 *
65 * a) it's loaded in the bootclasspath (i.e., is a system class)
66 * b) it takes > MIN_LOAD_TIME_MICROS us to load, and
67 * c) it's loaded by more than one process, or it's loaded by an
68 * application (i.e., not a long running service)
69 */
Bob Lee2e93f652009-08-11 01:16:03 -070070 Set<LoadedClass> toPreload = new TreeSet<LoadedClass>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
Bob Lee9d2d6e12009-08-13 14:41:54 -070072 // Preload classes that were loaded by at least 2 processes. Hopefully,
73 // the memory associated with these classes will be shared.
Bob Lee2e93f652009-08-11 01:16:03 -070074 for (LoadedClass loadedClass : root.loadedClasses.values()) {
Bob Lee9d2d6e12009-08-13 14:41:54 -070075 Set<String> names = loadedClass.processNames();
76 if (shouldPreload(loadedClass) && names.size() > 1) {
Bob Lee2e93f652009-08-11 01:16:03 -070077 toPreload.add(loadedClass);
78 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 }
80
Bob Lee9d2d6e12009-08-13 14:41:54 -070081 int initialSize = toPreload.size();
82 System.out.println(initialSize
83 + " classses were loaded by more than one app.");
84
85 // Preload eligable classes from applications (not long-running
86 // services).
Bob Lee2e93f652009-08-11 01:16:03 -070087 for (Proc proc : root.processes.values()) {
Bob Lee9d2d6e12009-08-13 14:41:54 -070088 if (proc.fromZygote() && !Policy.isService(proc.name)) {
89 for (Operation operation : proc.operations) {
90 LoadedClass loadedClass = operation.loadedClass;
91 if (shouldPreload(loadedClass)) {
92 toPreload.add(loadedClass);
93 }
94 }
95 }
Bob Lee2e93f652009-08-11 01:16:03 -070096 }
97
Bob Lee9d2d6e12009-08-13 14:41:54 -070098 System.out.println("Added " + (toPreload.size() - initialSize)
99 + " more to speed up applications.");
Bob Lee2e93f652009-08-11 01:16:03 -0700100
Bob Lee9d2d6e12009-08-13 14:41:54 -0700101 System.out.println(toPreload.size()
102 + " total classes will be preloaded.");
103
104 // Make classes that were implicitly loaded by the zygote explicit.
Bob Lee2e93f652009-08-11 01:16:03 -0700105 // This adds minimal overhead but avoid confusion about classes not
106 // appearing in the list.
Bob Lee9d2d6e12009-08-13 14:41:54 -0700107 addAllClassesFrom("zygote", root, toPreload);
Bob Lee2e93f652009-08-11 01:16:03 -0700108
109 for (LoadedClass loadedClass : toPreload) {
Bob Lee9d2d6e12009-08-13 14:41:54 -0700110 out.write(loadedClass.name + "\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 }
112
113 out.close();
114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 // Update data to reflect LoadedClass.preloaded changes.
Bob Lee2e93f652009-08-11 01:16:03 -0700116 for (LoadedClass loadedClass : toPreload) {
117 loadedClass.preloaded = true;
118 }
119 root.toFile(rootFile);
120 }
121
Bob Lee9d2d6e12009-08-13 14:41:54 -0700122 private static void addAllClassesFrom(String processName, Root root,
123 Set<LoadedClass> toPreload) {
Bob Lee2e93f652009-08-11 01:16:03 -0700124 for (Proc proc : root.processes.values()) {
Bob Lee9d2d6e12009-08-13 14:41:54 -0700125 if (proc.name.equals(processName)) {
Bob Lee2e93f652009-08-11 01:16:03 -0700126 for (Operation operation : proc.operations) {
Bob Lee9d2d6e12009-08-13 14:41:54 -0700127 boolean preloadable
128 = Policy.isPreloadable(operation.loadedClass);
129 if (preloadable) {
Bob Lee2e93f652009-08-11 01:16:03 -0700130 toPreload.add(operation.loadedClass);
131 }
132 }
133 }
134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 }
Bob Lee9d2d6e12009-08-13 14:41:54 -0700136
137 /**
138 * Returns true if the class should be preloaded.
139 */
140 private static boolean shouldPreload(LoadedClass clazz) {
141 return Policy.isPreloadable(clazz)
142 && clazz.medianTimeMicros() > MIN_LOAD_TIME_MICROS;
143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144}